@nest-omni/core 4.1.3-28 → 4.1.3-29

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 (33) hide show
  1. package/audit/interceptors/audit-action.interceptor.d.ts +1 -0
  2. package/audit/interceptors/audit-action.interceptor.js +5 -3
  3. package/audit/services/audit-action.service.d.ts +1 -0
  4. package/audit/services/audit-action.service.js +5 -3
  5. package/audit/services/operation-description.service.d.ts +1 -0
  6. package/audit/services/operation-description.service.js +5 -3
  7. package/audit/services/transaction-audit.service.d.ts +1 -0
  8. package/audit/services/transaction-audit.service.js +6 -4
  9. package/common/helpers/validation-metadata-helper.d.ts +57 -0
  10. package/common/helpers/validation-metadata-helper.js +109 -5
  11. package/decorators/examples/field-i18n.example.d.ts +294 -0
  12. package/decorators/examples/field-i18n.example.js +478 -0
  13. package/decorators/field.decorators.d.ts +23 -0
  14. package/decorators/field.decorators.js +7 -2
  15. package/decorators/translate.decorator.d.ts +26 -0
  16. package/decorators/translate.decorator.js +26 -1
  17. package/filters/bad-request.filter.js +15 -9
  18. package/http-client/decorators/http-client.decorators.d.ts +1 -0
  19. package/http-client/decorators/http-client.decorators.js +47 -30
  20. package/http-client/http-client.module.d.ts +8 -0
  21. package/http-client/http-client.module.js +24 -24
  22. package/http-client/services/http-client.service.js +56 -11
  23. package/http-client/utils/context-extractor.util.d.ts +2 -0
  24. package/http-client/utils/context-extractor.util.js +15 -3
  25. package/interceptors/index.d.ts +0 -1
  26. package/interceptors/index.js +0 -1
  27. package/interceptors/translation-interceptor.service.d.ts +7 -0
  28. package/interceptors/translation-interceptor.service.js +40 -8
  29. package/package.json +1 -1
  30. package/setup/bootstrap.setup.js +1 -1
  31. package/shared/services/api-config.service.js +18 -3
  32. package/interceptors/http-logging-interceptor.service.d.ts +0 -34
  33. package/interceptors/http-logging-interceptor.service.js +0 -138
@@ -14,6 +14,7 @@ export declare class AuditActionInterceptor implements NestInterceptor {
14
14
  private readonly contextService;
15
15
  private readonly summaryRepository;
16
16
  private readonly descriptionService?;
17
+ private readonly logger;
17
18
  constructor(reflector: Reflector, contextService: AuditContextService, summaryRepository: Repository<AuditActionSummaryEntity>, descriptionService?: OperationDescriptionService);
18
19
  intercept(context: ExecutionContext, next: CallHandler): Observable<any>;
19
20
  /**
@@ -20,6 +20,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
20
20
  step((generator = generator.apply(thisArg, _arguments || [])).next());
21
21
  });
22
22
  };
23
+ var AuditActionInterceptor_1;
23
24
  Object.defineProperty(exports, "__esModule", { value: true });
24
25
  exports.AuditActionInterceptor = void 0;
25
26
  const common_1 = require("@nestjs/common");
@@ -36,12 +37,13 @@ const audit_action_decorator_1 = require("../decorators/audit-action.decorator")
36
37
  * 审计动作拦截器
37
38
  * 在请求开始时创建审计动作上下文,在请求结束时生成汇总记录
38
39
  */
39
- let AuditActionInterceptor = class AuditActionInterceptor {
40
+ let AuditActionInterceptor = AuditActionInterceptor_1 = class AuditActionInterceptor {
40
41
  constructor(reflector, contextService, summaryRepository, descriptionService) {
41
42
  this.reflector = reflector;
42
43
  this.contextService = contextService;
43
44
  this.summaryRepository = summaryRepository;
44
45
  this.descriptionService = descriptionService;
46
+ this.logger = new common_1.Logger(AuditActionInterceptor_1.name);
45
47
  }
46
48
  intercept(context, next) {
47
49
  // 获取装饰器元数据
@@ -125,7 +127,7 @@ let AuditActionInterceptor = class AuditActionInterceptor {
125
127
  yield this.summaryRepository.save(summary);
126
128
  }
127
129
  catch (err) {
128
- console.error('Failed to generate audit action summary:', err);
130
+ this.logger.error('Failed to generate audit action summary:', err);
129
131
  }
130
132
  finally {
131
133
  // 清除审计动作上下文
@@ -204,7 +206,7 @@ let AuditActionInterceptor = class AuditActionInterceptor {
204
206
  }
205
207
  };
206
208
  exports.AuditActionInterceptor = AuditActionInterceptor;
207
- exports.AuditActionInterceptor = AuditActionInterceptor = __decorate([
209
+ exports.AuditActionInterceptor = AuditActionInterceptor = AuditActionInterceptor_1 = __decorate([
208
210
  (0, common_1.Injectable)(),
209
211
  __param(2, (0, common_1.Inject)((0, typeorm_1.getRepositoryToken)(entities_1.AuditActionSummaryEntity))),
210
212
  __param(3, (0, common_1.Optional)()),
@@ -47,6 +47,7 @@ export interface AuditActionResult {
47
47
  export declare class AuditActionService {
48
48
  private readonly contextService;
49
49
  private readonly auditService;
50
+ private readonly logger;
50
51
  constructor(contextService: AuditContextService, auditService: EntityAuditService);
51
52
  /**
52
53
  * 在审计动作上下文中执行操作
@@ -17,6 +17,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
17
17
  step((generator = generator.apply(thisArg, _arguments || [])).next());
18
18
  });
19
19
  };
20
+ var AuditActionService_1;
20
21
  Object.defineProperty(exports, "__esModule", { value: true });
21
22
  exports.AuditActionService = void 0;
22
23
  const common_1 = require("@nestjs/common");
@@ -27,10 +28,11 @@ const enums_1 = require("../enums");
27
28
  * 审计动作服务
28
29
  * 提供声明式的审计动作管理,自动关联同一业务操作的所有实体变化
29
30
  */
30
- let AuditActionService = class AuditActionService {
31
+ let AuditActionService = AuditActionService_1 = class AuditActionService {
31
32
  constructor(contextService, auditService) {
32
33
  this.contextService = contextService;
33
34
  this.auditService = auditService;
35
+ this.logger = new common_1.Logger(AuditActionService_1.name);
34
36
  }
35
37
  /**
36
38
  * 在审计动作上下文中执行操作
@@ -148,7 +150,7 @@ let AuditActionService = class AuditActionService {
148
150
  });
149
151
  }
150
152
  catch (err) {
151
- console.error('Failed to record audit action summary:', err);
153
+ this.logger.error('Failed to record audit action summary:', err);
152
154
  }
153
155
  });
154
156
  }
@@ -237,7 +239,7 @@ let AuditActionService = class AuditActionService {
237
239
  }
238
240
  };
239
241
  exports.AuditActionService = AuditActionService;
240
- exports.AuditActionService = AuditActionService = __decorate([
242
+ exports.AuditActionService = AuditActionService = AuditActionService_1 = __decorate([
241
243
  (0, common_1.Injectable)(),
242
244
  __metadata("design:paramtypes", [audit_context_service_1.AuditContextService,
243
245
  entity_audit_service_1.EntityAuditService])
@@ -12,6 +12,7 @@ export declare class OperationDescriptionService {
12
12
  private readonly auditLogRepository;
13
13
  private readonly manualOperationRepository;
14
14
  private readonly cacheService;
15
+ private readonly logger;
15
16
  private readonly CACHE_NAMESPACE;
16
17
  private readonly CACHE_TTL;
17
18
  constructor(templateRepository: Repository<OperationTemplateEntity>, transactionRepository: Repository<EntityTransactionEntity>, auditLogRepository: Repository<EntityAuditLogEntity>, manualOperationRepository: Repository<ManualOperationLogEntity>, cacheService: CacheService);
@@ -20,6 +20,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
20
20
  step((generator = generator.apply(thisArg, _arguments || [])).next());
21
21
  });
22
22
  };
23
+ var OperationDescriptionService_1;
23
24
  Object.defineProperty(exports, "__esModule", { value: true });
24
25
  exports.OperationDescriptionService = void 0;
25
26
  const common_1 = require("@nestjs/common");
@@ -31,13 +32,14 @@ const cache_1 = require("../../cache");
31
32
  * 操作描述服务
32
33
  * 负责根据模板和参数动态生成多语言描述
33
34
  */
34
- let OperationDescriptionService = class OperationDescriptionService {
35
+ let OperationDescriptionService = OperationDescriptionService_1 = class OperationDescriptionService {
35
36
  constructor(templateRepository, transactionRepository, auditLogRepository, manualOperationRepository, cacheService) {
36
37
  this.templateRepository = templateRepository;
37
38
  this.transactionRepository = transactionRepository;
38
39
  this.auditLogRepository = auditLogRepository;
39
40
  this.manualOperationRepository = manualOperationRepository;
40
41
  this.cacheService = cacheService;
42
+ this.logger = new common_1.Logger(OperationDescriptionService_1.name);
41
43
  // 缓存命名空间
42
44
  this.CACHE_NAMESPACE = 'audit:template';
43
45
  // 缓存TTL(30分钟)
@@ -302,7 +304,7 @@ let OperationDescriptionService = class OperationDescriptionService {
302
304
  };
303
305
  }
304
306
  catch (error) {
305
- console.error(`Failed to get description for transaction ${transaction.id}:`, error);
307
+ this.logger.error(`Failed to get description for transaction ${transaction.id}:`, error);
306
308
  }
307
309
  }
308
310
  return results;
@@ -410,7 +412,7 @@ let OperationDescriptionService = class OperationDescriptionService {
410
412
  }
411
413
  };
412
414
  exports.OperationDescriptionService = OperationDescriptionService;
413
- exports.OperationDescriptionService = OperationDescriptionService = __decorate([
415
+ exports.OperationDescriptionService = OperationDescriptionService = OperationDescriptionService_1 = __decorate([
414
416
  (0, common_1.Injectable)(),
415
417
  __param(0, (0, typeorm_1.InjectRepository)(entities_1.OperationTemplateEntity)),
416
418
  __param(1, (0, typeorm_1.InjectRepository)(entities_1.EntityTransactionEntity)),
@@ -12,6 +12,7 @@ export declare class TransactionAuditService {
12
12
  private readonly contextService;
13
13
  private readonly auditService;
14
14
  private readonly multiDbService;
15
+ private readonly logger;
15
16
  constructor(transactionRepository: Repository<EntityTransactionEntity>, contextService: AuditContextService, auditService: EntityAuditService, multiDbService: MultiDatabaseService);
16
17
  /**
17
18
  * 开始事务
@@ -20,6 +20,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
20
20
  step((generator = generator.apply(thisArg, _arguments || [])).next());
21
21
  });
22
22
  };
23
+ var TransactionAuditService_1;
23
24
  Object.defineProperty(exports, "__esModule", { value: true });
24
25
  exports.TransactionAuditService = void 0;
25
26
  const common_1 = require("@nestjs/common");
@@ -34,12 +35,13 @@ const transaction_1 = require("@nest-omni/transaction");
34
35
  /**
35
36
  * 事务审计服务
36
37
  */
37
- let TransactionAuditService = class TransactionAuditService {
38
+ let TransactionAuditService = TransactionAuditService_1 = class TransactionAuditService {
38
39
  constructor(transactionRepository, contextService, auditService, multiDbService) {
39
40
  this.transactionRepository = transactionRepository;
40
41
  this.contextService = contextService;
41
42
  this.auditService = auditService;
42
43
  this.multiDbService = multiDbService;
44
+ this.logger = new common_1.Logger(TransactionAuditService_1.name);
43
45
  }
44
46
  /**
45
47
  * 开始事务
@@ -182,7 +184,7 @@ let TransactionAuditService = class TransactionAuditService {
182
184
  yield this.rollbackSingleEntity(manager, entity, connectionName);
183
185
  }
184
186
  catch (error) {
185
- console.error(`Failed to rollback entity ${entity.entityType}:${entity.entityId} in connection ${connectionName}:`, error);
187
+ this.logger.error(`Failed to rollback entity ${entity.entityType}:${entity.entityId} in connection ${connectionName}:`, error);
186
188
  throw error;
187
189
  }
188
190
  }
@@ -223,7 +225,7 @@ let TransactionAuditService = class TransactionAuditService {
223
225
  }
224
226
  break;
225
227
  default:
226
- console.warn(`Unknown operation type: ${entity.operation}`);
228
+ this.logger.warn(`Unknown operation type: ${entity.operation}`);
227
229
  }
228
230
  });
229
231
  }
@@ -239,7 +241,7 @@ let TransactionAuditService = class TransactionAuditService {
239
241
  }
240
242
  };
241
243
  exports.TransactionAuditService = TransactionAuditService;
242
- exports.TransactionAuditService = TransactionAuditService = __decorate([
244
+ exports.TransactionAuditService = TransactionAuditService = TransactionAuditService_1 = __decorate([
243
245
  (0, common_1.Injectable)(),
244
246
  __param(0, (0, typeorm_1.InjectRepository)(entities_1.EntityTransactionEntity)),
245
247
  __metadata("design:paramtypes", [typeorm_2.Repository,
@@ -6,6 +6,8 @@ import type { Constructor } from '../types';
6
6
  export interface ValidationMetadata {
7
7
  /** 字段名称 */
8
8
  fieldName?: string;
9
+ /** i18n 翻译键 */
10
+ i18nKey?: string;
9
11
  /** 字段标签(多语言)- 使用 fieldLabel 避免命名冲突 */
10
12
  label?: string | {
11
13
  zh?: string;
@@ -21,6 +23,59 @@ export interface ValidationMetadata {
21
23
  /** 是否为数组 */
22
24
  each?: boolean;
23
25
  }
26
+ /**
27
+ * i18n 翻译函数类型
28
+ */
29
+ type I18nTranslateFunction = (key: string, options?: any) => string | Promise<string>;
30
+ /**
31
+ * 设置全局 i18n 翻译函数
32
+ *
33
+ * @example
34
+ * // 在 app.module.ts 或 main.ts 中设置
35
+ * import { setI18nTranslate } from './common/helpers/validation-metadata-helper';
36
+ * import { I18nService } from 'nestjs-i18n';
37
+ *
38
+ * setI18nTranslate((key, options) => i18nService.translate(key, options));
39
+ */
40
+ export declare function setI18nTranslate(fn: I18nTranslateFunction): void;
41
+ /**
42
+ * 获取全局 i18n 翻译函数
43
+ */
44
+ export declare function getI18nTranslate(): I18nTranslateFunction | null;
45
+ /**
46
+ * 解析字段标签
47
+ * 支持以下格式:
48
+ * 1. i18n key 字符串: "user.username"
49
+ * 2. 多语言对象: { zh: '用户名', en: 'Username' }
50
+ * 3. 普通字符串: "Username"
51
+ *
52
+ * @param label - 字段标签
53
+ * @param i18nKey - i18n 翻译键(优先使用)
54
+ * @param lang - 语言代码 (zh, en, 等)
55
+ * @returns 解析后的标签文本
56
+ */
57
+ export declare function resolveFieldLabel(label: string | {
58
+ zh?: string;
59
+ en?: string;
60
+ [lang: string]: string | undefined;
61
+ } | undefined, i18nKey?: string, lang?: string): string | {
62
+ zh?: string;
63
+ en?: string;
64
+ [lang: string]: string | undefined;
65
+ };
66
+ /**
67
+ * 翻译字段标签
68
+ * 将 i18n key 或多语言对象解析为最终文本
69
+ *
70
+ * @param labelOrKey - 标签、i18n key 或多语言对象
71
+ * @param lang - 语言代码
72
+ * @returns 翻译后的文本
73
+ */
74
+ export declare function translateFieldLabel(labelOrKey: string | {
75
+ zh?: string;
76
+ en?: string;
77
+ [lang: string]: string | undefined;
78
+ }, lang?: string): Promise<string>;
24
79
  /**
25
80
  * 存储验证元数据到装饰器
26
81
  *
@@ -47,9 +102,11 @@ export declare function getAllValidationMetadata(target: Constructor<any>): Reco
47
102
  /**
48
103
  * 获取字段的友好标签
49
104
  * 根据语言环境返回对应的标签
105
+ * 支持优先级:fieldLabel > i18nKey > fieldName
50
106
  *
51
107
  * @param metadata - 验证元数据
52
108
  * @param lang - 语言 (zh, en, 等)
53
109
  * @returns 字段标签
54
110
  */
55
111
  export declare function getFieldLabelForValidation(metadata: ValidationMetadata, lang?: string): string;
112
+ export {};
@@ -1,9 +1,106 @@
1
1
  "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.setI18nTranslate = setI18nTranslate;
13
+ exports.getI18nTranslate = getI18nTranslate;
14
+ exports.resolveFieldLabel = resolveFieldLabel;
15
+ exports.translateFieldLabel = translateFieldLabel;
3
16
  exports.setValidationMetadata = setValidationMetadata;
4
17
  exports.getValidationMetadata = getValidationMetadata;
5
18
  exports.getAllValidationMetadata = getAllValidationMetadata;
6
19
  exports.getFieldLabelForValidation = getFieldLabelForValidation;
20
+ /**
21
+ * 全局 i18n 翻译函数(由应用设置)
22
+ */
23
+ let globalI18nTranslate = null;
24
+ /**
25
+ * 设置全局 i18n 翻译函数
26
+ *
27
+ * @example
28
+ * // 在 app.module.ts 或 main.ts 中设置
29
+ * import { setI18nTranslate } from './common/helpers/validation-metadata-helper';
30
+ * import { I18nService } from 'nestjs-i18n';
31
+ *
32
+ * setI18nTranslate((key, options) => i18nService.translate(key, options));
33
+ */
34
+ function setI18nTranslate(fn) {
35
+ globalI18nTranslate = fn;
36
+ }
37
+ /**
38
+ * 获取全局 i18n 翻译函数
39
+ */
40
+ function getI18nTranslate() {
41
+ return globalI18nTranslate;
42
+ }
43
+ /**
44
+ * 解析字段标签
45
+ * 支持以下格式:
46
+ * 1. i18n key 字符串: "user.username"
47
+ * 2. 多语言对象: { zh: '用户名', en: 'Username' }
48
+ * 3. 普通字符串: "Username"
49
+ *
50
+ * @param label - 字段标签
51
+ * @param i18nKey - i18n 翻译键(优先使用)
52
+ * @param lang - 语言代码 (zh, en, 等)
53
+ * @returns 解析后的标签文本
54
+ */
55
+ function resolveFieldLabel(label, i18nKey, lang = 'zh') {
56
+ // 如果有 i18n key,返回 i18n key 对象(延迟解析)
57
+ if (i18nKey) {
58
+ return i18nKey;
59
+ }
60
+ // 如果有直接提供的 label
61
+ if (label) {
62
+ return label;
63
+ }
64
+ // 默认返回空字符串
65
+ return '';
66
+ }
67
+ /**
68
+ * 翻译字段标签
69
+ * 将 i18n key 或多语言对象解析为最终文本
70
+ *
71
+ * @param labelOrKey - 标签、i18n key 或多语言对象
72
+ * @param lang - 语言代码
73
+ * @returns 翻译后的文本
74
+ */
75
+ function translateFieldLabel(labelOrKey_1) {
76
+ return __awaiter(this, arguments, void 0, function* (labelOrKey, lang = 'zh') {
77
+ // 如果是普通字符串,直接返回
78
+ if (typeof labelOrKey === 'string') {
79
+ // 尝试作为 i18n key 翻译
80
+ if (globalI18nTranslate && labelOrKey.includes('.')) {
81
+ try {
82
+ const translated = yield globalI18nTranslate(labelOrKey, { lang });
83
+ if (translated && translated !== labelOrKey) {
84
+ return translated;
85
+ }
86
+ }
87
+ catch (_a) {
88
+ // 翻译失败,返回原始 key
89
+ }
90
+ }
91
+ return labelOrKey;
92
+ }
93
+ // 如果是多语言对象,返回对应语言的文本
94
+ if (typeof labelOrKey === 'object' && labelOrKey !== null) {
95
+ return (labelOrKey[lang] ||
96
+ labelOrKey.zh ||
97
+ labelOrKey.en ||
98
+ Object.values(labelOrKey).find((v) => v) ||
99
+ '');
100
+ }
101
+ return '';
102
+ });
103
+ }
7
104
  /**
8
105
  * 验证元数据存储键
9
106
  */
@@ -44,17 +141,24 @@ function getAllValidationMetadata(target) {
44
141
  /**
45
142
  * 获取字段的友好标签
46
143
  * 根据语言环境返回对应的标签
144
+ * 支持优先级:fieldLabel > i18nKey > fieldName
47
145
  *
48
146
  * @param metadata - 验证元数据
49
147
  * @param lang - 语言 (zh, en, 等)
50
148
  * @returns 字段标签
51
149
  */
52
150
  function getFieldLabelForValidation(metadata, lang = 'zh') {
53
- if (!metadata.label) {
54
- return metadata.fieldName || '';
151
+ // 如果有 fieldLabel,直接使用
152
+ if (metadata.label) {
153
+ if (typeof metadata.label === 'string') {
154
+ return metadata.label;
155
+ }
156
+ return metadata.label[lang] || metadata.label.zh || metadata.label.en || '';
55
157
  }
56
- if (typeof metadata.label === 'string') {
57
- return metadata.label;
158
+ // 如果有 i18nKey,返回 i18nKey(会在运行时翻译)
159
+ if (metadata.i18nKey) {
160
+ return metadata.i18nKey;
58
161
  }
59
- return metadata.label[lang] || metadata.label.zh || metadata.label.en || metadata.fieldName || '';
162
+ // 默认返回字段名
163
+ return metadata.fieldName || '';
60
164
  }