@nest-omni/core 4.1.3-10 → 4.1.3-11

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.
@@ -1,4 +1,4 @@
1
- import { AuditOperation, MaskingStrategy, RecordStrategy } from '../enums/audit.enums';
1
+ import { AuditOperation, MaskingStrategy, RecordStrategy, RollbackActionType, ChangeType } from '../enums/audit.enums';
2
2
  /**
3
3
  * 审计上下文
4
4
  */
@@ -124,12 +124,38 @@ export interface AuditConfig {
124
124
  /**
125
125
  * 实体级别审计配置
126
126
  */
127
+ /**
128
+ * 实体审计配置
129
+ *
130
+ * @description
131
+ * 支持基础审计配置
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * @EntityAudit({
136
+ * enabled: true,
137
+ * excludeFields: ['password'],
138
+ * maskFields: ['email', 'phone'],
139
+ * templateKey: 'user',
140
+ * })
141
+ * ```
142
+ */
127
143
  export interface EntityAuditConfig {
128
144
  enabled?: boolean;
129
145
  strategy?: RecordStrategy;
130
146
  includeFields?: string[];
131
147
  excludeFields?: string[];
132
148
  maskFields?: string[];
149
+ /**
150
+ * 操作模板键前缀
151
+ * @example 'user' -> 生成 'user.create', 'user.update', 'user.delete'
152
+ */
153
+ templateKey?: string;
154
+ /**
155
+ * @deprecated 使用 maskFields 代替
156
+ * 敏感字段列表(别名,用于兼容旧版本)
157
+ */
158
+ sensitiveFields?: string[];
133
159
  }
134
160
  /**
135
161
  * 操作级别审计配置
@@ -142,7 +168,25 @@ export interface OperationAuditConfig {
142
168
  * 字段显示选项
143
169
  */
144
170
  export interface FieldDisplayOptions {
145
- displayName?: string;
171
+ /**
172
+ * 字段标签(支持多语言)
173
+ * @example
174
+ * // 单语言
175
+ * label: '姓名'
176
+ *
177
+ * // 多语言
178
+ * label: { zh: '姓名', en: 'Name' }
179
+ */
180
+ label?: string | Record<string, string>;
181
+ /**
182
+ * 字段值的多语言标签映射
183
+ * @example
184
+ * valueLabels: {
185
+ * active: { zh: '激活', en: 'Active' },
186
+ * inactive: { zh: '未激活', en: 'Inactive' }
187
+ * }
188
+ */
189
+ valueLabels?: Record<string, Record<string, string>>;
146
190
  sensitive?: boolean;
147
191
  formatter?: (value: any) => string;
148
192
  }
@@ -159,3 +203,97 @@ export interface ControllerAuditOptions {
159
203
  export interface MethodAuditOptions {
160
204
  enabled?: boolean;
161
205
  }
206
+ /**
207
+ * 变更详情
208
+ */
209
+ export interface ChangeDetail {
210
+ fieldName: string;
211
+ fieldLabels?: Record<string, string>;
212
+ oldValue: any;
213
+ newValue: any;
214
+ displayOldValue?: Record<string, string>;
215
+ displayNewValue?: Record<string, string>;
216
+ changeType: ChangeType;
217
+ }
218
+ /**
219
+ * 回滚操作
220
+ */
221
+ export interface RollbackAction {
222
+ type: RollbackActionType;
223
+ action: string;
224
+ params: Record<string, any>;
225
+ order: number;
226
+ handler?: string;
227
+ }
228
+ /**
229
+ * 操作模板配置(用于数据库存储)
230
+ */
231
+ export interface OperationTemplateData {
232
+ key: string;
233
+ entityName: string;
234
+ operation: AuditOperation;
235
+ nameTemplates: Record<string, string>;
236
+ descriptionTemplates: Record<string, string>;
237
+ fieldLabels?: Record<string, Record<string, string>>;
238
+ valueDisplays?: Record<string, Record<string, Record<string, string>>>;
239
+ }
240
+ /**
241
+ * 手动操作日志数据
242
+ */
243
+ export interface ManualOperationData {
244
+ transactionId: string;
245
+ operationTemplateKey: string;
246
+ descriptionParams: Record<string, any>;
247
+ userId?: string;
248
+ username?: string;
249
+ requestIp?: string;
250
+ rollbackActions?: RollbackAction[];
251
+ }
252
+ /**
253
+ * 手动日志记录选项(支持三种模式)
254
+ */
255
+ export interface ManualLogOptions {
256
+ templateKey?: string;
257
+ descriptionParams?: Record<string, any>;
258
+ description?: string | Record<string, string>;
259
+ descriptionTemplate?: Record<string, string>;
260
+ userId?: string;
261
+ username?: string;
262
+ requestIp?: string;
263
+ rollbackActions?: RollbackAction[];
264
+ transactionId?: string;
265
+ autoCreateTransaction?: boolean;
266
+ }
267
+ /**
268
+ * 方法审计选项(支持模板和回滚)
269
+ */
270
+ export interface AuditOperationOptions {
271
+ templateKey: string;
272
+ descriptionParams?: (args: any[], result: any, context: any) => Record<string, any>;
273
+ rollbackActions?: (args: any[], result: any, context: any) => RollbackAction[];
274
+ autoTransaction?: boolean;
275
+ }
276
+ /**
277
+ * 增强的实体审计配置(支持多语言)
278
+ */
279
+ export interface EnhancedEntityAuditConfig extends EntityAuditConfig {
280
+ templateKey?: string;
281
+ fieldLabels?: Record<string, Record<string, string>>;
282
+ valueDisplays?: Record<string, Record<string, Record<string, string>>>;
283
+ }
284
+ /**
285
+ * 事务描述结果
286
+ */
287
+ export interface TransactionDescription {
288
+ operationName: string;
289
+ description: string;
290
+ changes: Array<{
291
+ entityName?: string;
292
+ entityId?: string;
293
+ operation?: AuditOperation;
294
+ type?: string;
295
+ description: string;
296
+ details: any;
297
+ createdAt: Date;
298
+ }>;
299
+ }
@@ -1,7 +1,7 @@
1
1
  import { Repository, EntityManager } from 'typeorm';
2
- import { EntityAuditLogEntity, EntityTransactionEntity } from '../entities';
2
+ import { EntityAuditLogEntity, EntityTransactionEntity, ManualOperationLogEntity } from '../entities';
3
3
  import { AuditOperation } from '../enums';
4
- import { AuditConfig, IAuditStrategy, EntityDifference, RestoreOptions, RestoreResult, PreCheckResult } from '../interfaces';
4
+ import { AuditConfig, IAuditStrategy, EntityDifference, RestoreOptions, RestoreResult, PreCheckResult, ManualOperationData, ChangeDetail, RollbackAction } from '../interfaces';
5
5
  import { AuditContextService } from './audit-context.service';
6
6
  import { MultiDatabaseService } from './multi-database.service';
7
7
  import { PageDto } from '../../common/dto';
@@ -12,13 +12,14 @@ import { AuditLogQueryDto } from '../dto';
12
12
  export declare class EntityAuditService {
13
13
  private readonly auditLogRepository;
14
14
  private readonly transactionRepository;
15
+ private readonly manualOperationRepository;
15
16
  private readonly entityManager;
16
17
  private readonly contextService;
17
18
  private readonly multiDbService;
18
19
  private readonly auditStrategy;
19
20
  private readonly config?;
20
21
  private readonly auditConnectionName;
21
- constructor(auditLogRepository: Repository<EntityAuditLogEntity>, transactionRepository: Repository<EntityTransactionEntity>, entityManager: EntityManager, contextService: AuditContextService, multiDbService: MultiDatabaseService, auditStrategy?: IAuditStrategy, config?: AuditConfig, auditConnectionName?: string);
22
+ constructor(auditLogRepository: Repository<EntityAuditLogEntity>, transactionRepository: Repository<EntityTransactionEntity>, manualOperationRepository: Repository<ManualOperationLogEntity>, entityManager: EntityManager, contextService: AuditContextService, multiDbService: MultiDatabaseService, auditStrategy?: IAuditStrategy, config?: AuditConfig, auditConnectionName?: string);
22
23
  /**
23
24
  * 记录实体变更
24
25
  */
@@ -91,4 +92,72 @@ export declare class EntityAuditService {
91
92
  * 检测冲突
92
93
  */
93
94
  private detectConflicts;
95
+ /**
96
+ * 增强的记录实体变更(支持模板和结构化变更详情)
97
+ * @param data 审计数据
98
+ * @returns 审计日志实体
99
+ */
100
+ logEntityChangeWithTemplate(data: {
101
+ entityType: string;
102
+ entityId: string;
103
+ operation: AuditOperation;
104
+ oldValue?: Record<string, any>;
105
+ newValue?: Record<string, any>;
106
+ changedFields?: string[];
107
+ operationTemplateKey?: string;
108
+ descriptionParams?: Record<string, any>;
109
+ changeDetails?: ChangeDetail[];
110
+ rollbackActions?: RollbackAction[];
111
+ metadata?: Record<string, any>;
112
+ }): Promise<EntityAuditLogEntity | null>;
113
+ /**
114
+ * 记录手动操作
115
+ * @param data 手动操作数据
116
+ * @returns 手动操作日志实体
117
+ */
118
+ logManualOperation(data: ManualOperationData): Promise<ManualOperationLogEntity>;
119
+ /**
120
+ * 在事务中执行操作
121
+ * @param fn 执行函数
122
+ * @param options 事务选项
123
+ * @returns 执���结果
124
+ */
125
+ withTransaction<T>(fn: (transactionId: string) => Promise<T>, options?: {
126
+ userId?: string;
127
+ username?: string;
128
+ requestIp?: string;
129
+ operationTemplateKey?: string;
130
+ descriptionParams?: Record<string, any>;
131
+ metadata?: Record<string, any>;
132
+ }): Promise<T>;
133
+ /**
134
+ * 获取当前事务ID
135
+ * @returns 当前事务ID或null
136
+ */
137
+ getCurrentTransactionId(): Promise<string | null>;
138
+ /**
139
+ * 设置当前事务ID
140
+ * @param transactionId 事务ID
141
+ */
142
+ setCurrentTransactionId(transactionId: string | null): Promise<void>;
143
+ /**
144
+ * 开始事务
145
+ * @param userId 用户ID
146
+ * @param userName 用户名
147
+ * @param ip IP地址
148
+ * @param operationTemplateKey 操作模板键
149
+ * @param descriptionParams 描述参数
150
+ * @returns 事务ID
151
+ */
152
+ beginTransaction(userId?: string, userName?: string, ip?: string, operationTemplateKey?: string, descriptionParams?: Record<string, any>): Promise<string>;
153
+ /**
154
+ * 提交事务
155
+ * @param transactionId 事务ID
156
+ */
157
+ commitTransaction(transactionId: string): Promise<void>;
158
+ /**
159
+ * 回滚事务
160
+ * @param transactionId 事务ID
161
+ */
162
+ rollbackTransaction(transactionId: string): Promise<void>;
94
163
  }
@@ -36,9 +36,10 @@ const dto_1 = require("../../common/dto");
36
36
  * 实体审计服务
37
37
  */
38
38
  let EntityAuditService = class EntityAuditService {
39
- constructor(auditLogRepository, transactionRepository, entityManager, contextService, multiDbService, auditStrategy = new audit_strategy_service_1.DefaultAuditStrategy(), config, auditConnectionName) {
39
+ constructor(auditLogRepository, transactionRepository, manualOperationRepository, entityManager, contextService, multiDbService, auditStrategy = new audit_strategy_service_1.DefaultAuditStrategy(), config, auditConnectionName) {
40
40
  this.auditLogRepository = auditLogRepository;
41
41
  this.transactionRepository = transactionRepository;
42
+ this.manualOperationRepository = manualOperationRepository;
42
43
  this.entityManager = entityManager;
43
44
  this.contextService = contextService;
44
45
  this.multiDbService = multiDbService;
@@ -554,20 +555,223 @@ let EntityAuditService = class EntityAuditService {
554
555
  }
555
556
  return conflicts;
556
557
  }
558
+ // ========== 新增方法:支持模板和手动操作 ==========
559
+ /**
560
+ * 增强的记录实体变更(支持模板和结构化变更详情)
561
+ * @param data 审计数据
562
+ * @returns 审计日志实体
563
+ */
564
+ logEntityChangeWithTemplate(data) {
565
+ return __awaiter(this, void 0, void 0, function* () {
566
+ var _a, _b, _c, _d, _e, _f, _g;
567
+ // 检查是否应该记录
568
+ if (!this.auditStrategy.shouldRecord(data.entityType, data.operation)) {
569
+ return null;
570
+ }
571
+ // 获取记录策略
572
+ const recordStrategy = this.auditStrategy.getRecordStrategy(data.entityType, data.operation);
573
+ if (recordStrategy === enums_1.RecordStrategy.DISABLED) {
574
+ return null;
575
+ }
576
+ // 获取字段过滤器
577
+ const fieldFilter = this.auditStrategy.getFieldFilter(data.entityType);
578
+ // 过滤和脱敏字段
579
+ const filteredOldValue = this.filterAndMaskFields(data.oldValue || {}, fieldFilter);
580
+ const filteredNewValue = this.filterAndMaskFields(data.newValue || {}, fieldFilter);
581
+ // 计算变更字段
582
+ const changedFields = data.changedFields || this.calculateChangedFields(filteredOldValue, filteredNewValue);
583
+ const changedFieldPaths = this.calculateChangedFieldPaths(filteredOldValue, filteredNewValue);
584
+ // 获取上下文信息
585
+ const context = yield this.contextService.getCurrentContext();
586
+ // 如果没有提供操作模板键,使用默认模板
587
+ const operationTemplateKey = data.operationTemplateKey || `${data.entityType}.${data.operation}`;
588
+ // 如果没有提供描述参数,使用实体数据
589
+ const descriptionParams = data.descriptionParams || Object.assign(Object.assign(Object.assign({}, filteredOldValue), filteredNewValue), { changedFields, changedFieldsCount: changedFields.length });
590
+ // 创建审计日志
591
+ const auditLog = this.auditLogRepository.create({
592
+ entityType: data.entityType,
593
+ entityId: data.entityId,
594
+ operation: data.operation,
595
+ oldValue: filteredOldValue,
596
+ newValue: filteredNewValue,
597
+ changedFields,
598
+ changedFieldPaths: changedFieldPaths.join(','),
599
+ userId: context.userId || ((_a = data.metadata) === null || _a === void 0 ? void 0 : _a.userId),
600
+ username: context.username || ((_b = data.metadata) === null || _b === void 0 ? void 0 : _b.username),
601
+ requestId: context.requestId || ((_c = data.metadata) === null || _c === void 0 ? void 0 : _c.requestId),
602
+ requestIp: context.requestIp || ((_d = data.metadata) === null || _d === void 0 ? void 0 : _d.requestIp),
603
+ userAgent: context.userAgent || ((_e = data.metadata) === null || _e === void 0 ? void 0 : _e.userAgent),
604
+ description: this.generateDescription(data.operation, data.entityType, data.entityId, changedFields),
605
+ hashChain: ((_g = (_f = this.config) === null || _f === void 0 ? void 0 : _f.security) === null || _g === void 0 ? void 0 : _g.hashChainEnabled)
606
+ ? yield this.generateHashChain(data.entityType, data.entityId, filteredNewValue)
607
+ : undefined,
608
+ // 新增字段
609
+ operationTemplateKey,
610
+ descriptionParams,
611
+ changeDetails: data.changeDetails,
612
+ rollbackActions: data.rollbackActions,
613
+ });
614
+ // 保存变更日志
615
+ const savedLog = yield this.auditLogRepository.save(auditLog);
616
+ return savedLog;
617
+ });
618
+ }
619
+ /**
620
+ * 记录手动操作
621
+ * @param data 手动操作数据
622
+ * @returns 手动操作日志实体
623
+ */
624
+ logManualOperation(data) {
625
+ return __awaiter(this, void 0, void 0, function* () {
626
+ // 获取上下文信息
627
+ const context = yield this.contextService.getCurrentContext();
628
+ const manualLog = this.manualOperationRepository.create({
629
+ transactionId: data.transactionId,
630
+ operationTemplateKey: data.operationTemplateKey,
631
+ descriptionParams: data.descriptionParams,
632
+ userId: data.userId || context.userId,
633
+ username: data.username || context.username,
634
+ requestIp: data.requestIp || context.requestIp,
635
+ rollbackActions: data.rollbackActions || [],
636
+ });
637
+ return yield this.manualOperationRepository.save(manualLog);
638
+ });
639
+ }
640
+ /**
641
+ * 在事务中执行操作
642
+ * @param fn 执行函数
643
+ * @param options 事务选项
644
+ * @returns 执���结果
645
+ */
646
+ withTransaction(fn, options) {
647
+ return __awaiter(this, void 0, void 0, function* () {
648
+ var _a;
649
+ // 获取上下文信息
650
+ const context = yield this.contextService.getCurrentContext();
651
+ // 创建事务
652
+ const transaction = this.transactionRepository.create({
653
+ description: ((_a = options === null || options === void 0 ? void 0 : options.descriptionParams) === null || _a === void 0 ? void 0 : _a.description) || 'Transaction',
654
+ status: 'PENDING',
655
+ entities: [],
656
+ userId: (options === null || options === void 0 ? void 0 : options.userId) || context.userId,
657
+ username: (options === null || options === void 0 ? void 0 : options.username) || context.username,
658
+ requestIp: (options === null || options === void 0 ? void 0 : options.requestIp) || context.requestIp,
659
+ operationTemplateKey: options === null || options === void 0 ? void 0 : options.operationTemplateKey,
660
+ descriptionParams: options === null || options === void 0 ? void 0 : options.descriptionParams,
661
+ metadata: options === null || options === void 0 ? void 0 : options.metadata,
662
+ });
663
+ const savedTransaction = yield this.transactionRepository.save(transaction);
664
+ const transactionId = savedTransaction.id;
665
+ try {
666
+ // 设置事务ID到上下文
667
+ yield this.contextService.setContext(Object.assign(Object.assign({}, context), { transactionId }));
668
+ // 执行操作
669
+ const result = yield fn(transactionId);
670
+ // 提交事务
671
+ yield this.transactionRepository.update(transactionId, {
672
+ status: 'COMMITTED',
673
+ completedAt: new Date(),
674
+ });
675
+ return result;
676
+ }
677
+ catch (error) {
678
+ // 回滚事务
679
+ yield this.transactionRepository.update(transactionId, {
680
+ status: 'ROLLED_BACK',
681
+ completedAt: new Date(),
682
+ });
683
+ throw error;
684
+ }
685
+ });
686
+ }
687
+ /**
688
+ * 获取当前事务ID
689
+ * @returns 当前事务ID或null
690
+ */
691
+ getCurrentTransactionId() {
692
+ return __awaiter(this, void 0, void 0, function* () {
693
+ const context = yield this.contextService.getCurrentContext();
694
+ return context.transactionId || null;
695
+ });
696
+ }
697
+ /**
698
+ * 设置当前事务ID
699
+ * @param transactionId 事务ID
700
+ */
701
+ setCurrentTransactionId(transactionId) {
702
+ return __awaiter(this, void 0, void 0, function* () {
703
+ const context = yield this.contextService.getCurrentContext();
704
+ yield this.contextService.setContext(Object.assign(Object.assign({}, context), { transactionId }));
705
+ });
706
+ }
707
+ /**
708
+ * 开始事务
709
+ * @param userId 用户ID
710
+ * @param userName 用户名
711
+ * @param ip IP地址
712
+ * @param operationTemplateKey 操作模板键
713
+ * @param descriptionParams 描述参数
714
+ * @returns 事务ID
715
+ */
716
+ beginTransaction(userId, userName, ip, operationTemplateKey, descriptionParams) {
717
+ return __awaiter(this, void 0, void 0, function* () {
718
+ // 获取上下文信息
719
+ const context = yield this.contextService.getCurrentContext();
720
+ // 创建事务
721
+ const transaction = this.transactionRepository.create({
722
+ description: (descriptionParams === null || descriptionParams === void 0 ? void 0 : descriptionParams.description) || 'Transaction',
723
+ status: 'pending',
724
+ entities: [],
725
+ userId: userId || context.userId,
726
+ username: userName || context.username,
727
+ requestIp: ip || context.requestIp,
728
+ operationTemplateKey,
729
+ descriptionParams,
730
+ });
731
+ const savedTransaction = yield this.transactionRepository.save(transaction);
732
+ return savedTransaction.id;
733
+ });
734
+ }
735
+ /**
736
+ * 提交事务
737
+ * @param transactionId 事务ID
738
+ */
739
+ commitTransaction(transactionId) {
740
+ return __awaiter(this, void 0, void 0, function* () {
741
+ yield this.transactionRepository.update(transactionId, {
742
+ status: 'committed',
743
+ completedAt: new Date(),
744
+ });
745
+ });
746
+ }
747
+ /**
748
+ * 回滚事务
749
+ * @param transactionId 事务ID
750
+ */
751
+ rollbackTransaction(transactionId) {
752
+ return __awaiter(this, void 0, void 0, function* () {
753
+ yield this.transactionRepository.update(transactionId, {
754
+ status: 'rolled_back',
755
+ completedAt: new Date(),
756
+ });
757
+ });
758
+ }
557
759
  };
558
760
  exports.EntityAuditService = EntityAuditService;
559
761
  exports.EntityAuditService = EntityAuditService = __decorate([
560
762
  (0, common_1.Injectable)(),
561
763
  __param(0, (0, typeorm_1.InjectRepository)(entities_1.EntityAuditLogEntity)),
562
764
  __param(1, (0, typeorm_1.InjectRepository)(entities_1.EntityTransactionEntity)),
563
- __param(2, (0, common_1.Inject)('AUDIT_ENTITY_MANAGER')),
564
- __param(5, (0, common_1.Optional)()),
565
- __param(5, (0, common_1.Inject)('AUDIT_STRATEGY')),
765
+ __param(2, (0, typeorm_1.InjectRepository)(entities_1.ManualOperationLogEntity)),
766
+ __param(3, (0, common_1.Inject)('AUDIT_ENTITY_MANAGER')),
566
767
  __param(6, (0, common_1.Optional)()),
567
- __param(6, (0, common_1.Inject)('AUDIT_CONFIG')),
768
+ __param(6, (0, common_1.Inject)('AUDIT_STRATEGY')),
568
769
  __param(7, (0, common_1.Optional)()),
569
- __param(7, (0, common_1.Inject)('AUDIT_CONNECTION_NAME')),
770
+ __param(7, (0, common_1.Inject)('AUDIT_CONFIG')),
771
+ __param(8, (0, common_1.Optional)()),
772
+ __param(8, (0, common_1.Inject)('AUDIT_CONNECTION_NAME')),
570
773
  __metadata("design:paramtypes", [typeorm_2.Repository,
774
+ typeorm_2.Repository,
571
775
  typeorm_2.Repository,
572
776
  typeorm_2.EntityManager,
573
777
  audit_context_service_1.AuditContextService,
@@ -3,3 +3,5 @@ export * from './audit-strategy.service';
3
3
  export * from './entity-audit.service';
4
4
  export * from './transaction-audit.service';
5
5
  export * from './multi-database.service';
6
+ export * from './operation-description.service';
7
+ export * from './manual-audit-log.service';
@@ -19,3 +19,5 @@ __exportStar(require("./audit-strategy.service"), exports);
19
19
  __exportStar(require("./entity-audit.service"), exports);
20
20
  __exportStar(require("./transaction-audit.service"), exports);
21
21
  __exportStar(require("./multi-database.service"), exports);
22
+ __exportStar(require("./operation-description.service"), exports);
23
+ __exportStar(require("./manual-audit-log.service"), exports);
@@ -18,7 +18,6 @@ var HttpClientModule_1;
18
18
  Object.defineProperty(exports, "__esModule", { value: true });
19
19
  exports.HttpClientModule = void 0;
20
20
  const common_1 = require("@nestjs/common");
21
- const schedule_1 = require("@nestjs/schedule");
22
21
  const config_1 = require("@nestjs/config");
23
22
  const typeorm_1 = require("@nestjs/typeorm");
24
23
  const cache_service_1 = require("../cache/cache.service");
@@ -41,7 +40,7 @@ let HttpClientModule = HttpClientModule_1 = class HttpClientModule {
41
40
  * 动态注册HTTP客户端模块
42
41
  */
43
42
  static forRoot(config = {}) {
44
- var _a, _b, _c;
43
+ var _a, _b;
45
44
  // 基础服务提供者
46
45
  const baseProviders = [
47
46
  {
@@ -87,9 +86,6 @@ let HttpClientModule = HttpClientModule_1 = class HttpClientModule {
87
86
  if ((_b = (_a = config.logging) === null || _a === void 0 ? void 0 : _a.databaseLogging) === null || _b === void 0 ? void 0 : _b.enabled) {
88
87
  dynamicImports.push(typeorm_1.TypeOrmModule.forFeature([entities_1.HttpLogEntity]));
89
88
  }
90
- if ((_c = config.logCleanup) === null || _c === void 0 ? void 0 : _c.enabled) {
91
- dynamicImports.push(schedule_1.ScheduleModule.forRoot());
92
- }
93
89
  return {
94
90
  module: HttpClientModule_1,
95
91
  imports: dynamicImports,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nest-omni/core",
3
- "version": "4.1.3-10",
3
+ "version": "4.1.3-11",
4
4
  "description": "A comprehensive NestJS framework for building enterprise-grade applications with best practices",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -23,12 +23,12 @@ export declare class LockHeartbeatService implements OnModuleInit, OnModuleDestr
23
23
  private heartbeatTimer;
24
24
  /**
25
25
  * Heartbeat interval in milliseconds
26
- * @default 10000 (10 seconds)
26
+ * @default 5000 (5 seconds) - reduced for faster failure detection
27
27
  */
28
28
  private readonly heartbeatInterval;
29
29
  /**
30
30
  * Heartbeat TTL in seconds (3x interval for safety)
31
- * @default 30 (30 seconds)
31
+ * @default 15 (15 seconds) - adjusted to match new interval
32
32
  */
33
33
  private readonly heartbeatTtl;
34
34
  constructor();
@@ -44,14 +44,14 @@ let LockHeartbeatService = LockHeartbeatService_1 = class LockHeartbeatService {
44
44
  this.heartbeatTimer = null;
45
45
  /**
46
46
  * Heartbeat interval in milliseconds
47
- * @default 10000 (10 seconds)
47
+ * @default 5000 (5 seconds) - reduced for faster failure detection
48
48
  */
49
- this.heartbeatInterval = 10000;
49
+ this.heartbeatInterval = 5000;
50
50
  /**
51
51
  * Heartbeat TTL in seconds (3x interval for safety)
52
- * @default 30 (30 seconds)
52
+ * @default 15 (15 seconds) - adjusted to match new interval
53
53
  */
54
- this.heartbeatTtl = 30;
54
+ this.heartbeatTtl = 15;
55
55
  this.instanceId = this.getInstanceId();
56
56
  }
57
57
  onModuleInit() {
@@ -69,6 +69,24 @@ export interface LockOptions {
69
69
  * @default 0 (no automatic extension)
70
70
  */
71
71
  autoExtend?: number;
72
+ /**
73
+ * Whether to use exponential backoff for retry attempts
74
+ * If true, retry delay will increase exponentially: retryDelay * 2^(attempt-1)
75
+ * @default false
76
+ */
77
+ useExponentialBackoff?: boolean;
78
+ /**
79
+ * Maximum retry delay in milliseconds when using exponential backoff
80
+ * Ensures retry delay doesn't grow indefinitely
81
+ * @default 60000 (60 seconds)
82
+ */
83
+ maxRetryDelay?: number;
84
+ /**
85
+ * Random jitter to add to retry delay in milliseconds
86
+ * Helps prevent synchronized retries across multiple instances
87
+ * @default 0 (no jitter)
88
+ */
89
+ retryJitter?: number;
72
90
  }
73
91
  export interface LockResult {
74
92
  /**