@nest-omni/core 4.1.3-3 → 4.1.3-30
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 +1 -0
- package/audit/audit.module.js +51 -2
- package/audit/controllers/audit.controller.d.ts +57 -1
- package/audit/controllers/audit.controller.js +43 -0
- package/audit/decorators/audit-action.decorator.d.ts +74 -0
- package/audit/decorators/audit-action.decorator.js +42 -0
- package/audit/decorators/audit-controller.decorator.d.ts +1 -1
- package/audit/decorators/audit-controller.decorator.js +2 -2
- package/audit/decorators/audit-operation.decorator.d.ts +0 -7
- package/audit/decorators/audit-operation.decorator.js +0 -7
- package/audit/decorators/entity-audit.decorator.d.ts +78 -2
- package/audit/decorators/entity-audit.decorator.js +145 -4
- package/audit/decorators/index.d.ts +2 -0
- package/audit/decorators/index.js +2 -0
- package/audit/dto/audit-action-query.dto.d.ts +13 -0
- package/audit/dto/audit-action-query.dto.js +77 -0
- package/audit/dto/index.d.ts +1 -0
- package/audit/dto/index.js +1 -0
- package/audit/entities/audit-action-summary.entity.d.ts +23 -0
- package/audit/entities/audit-action-summary.entity.js +101 -0
- package/audit/entities/entity-audit-log.entity.d.ts +7 -2
- package/audit/entities/entity-audit-log.entity.js +45 -9
- package/audit/entities/entity-transaction.entity.d.ts +8 -2
- package/audit/entities/entity-transaction.entity.js +39 -3
- package/audit/entities/index.d.ts +3 -0
- package/audit/entities/index.js +3 -0
- package/audit/entities/manual-operation-log.entity.d.ts +0 -2
- package/audit/entities/manual-operation-log.entity.js +8 -9
- package/audit/enums/audit.enums.d.ts +14 -6
- package/audit/enums/audit.enums.js +18 -9
- package/audit/examples/decorator-value-mapping.example.d.ts +70 -0
- package/audit/examples/decorator-value-mapping.example.js +414 -0
- package/audit/index.d.ts +5 -1
- package/audit/index.js +29 -2
- package/audit/interceptors/audit-action.interceptor.d.ts +39 -0
- package/audit/interceptors/audit-action.interceptor.js +217 -0
- package/audit/interceptors/audit.interceptor.d.ts +1 -0
- package/audit/interceptors/audit.interceptor.js +19 -11
- package/audit/interceptors/index.d.ts +1 -0
- package/audit/interceptors/index.js +1 -0
- package/audit/interfaces/audit.interfaces.d.ts +132 -4
- package/audit/services/audit-action.service.d.ts +142 -0
- package/audit/services/audit-action.service.js +246 -0
- package/audit/services/audit-context.service.d.ts +91 -0
- package/audit/services/audit-context.service.js +170 -0
- package/audit/services/entity-audit.service.d.ts +220 -9
- package/audit/services/entity-audit.service.js +761 -72
- package/audit/services/index.d.ts +3 -0
- package/audit/services/index.js +3 -0
- package/audit/services/manual-audit-log.service.d.ts +23 -23
- package/audit/services/manual-audit-log.service.js +34 -57
- package/audit/services/multi-database.service.d.ts +0 -5
- package/audit/services/multi-database.service.js +0 -24
- package/audit/services/operation-description.service.d.ts +14 -3
- package/audit/services/operation-description.service.js +165 -26
- package/audit/services/transaction-audit.service.d.ts +1 -0
- package/audit/services/transaction-audit.service.js +12 -9
- package/audit/subscribers/entity-audit.subscriber.d.ts +5 -0
- package/audit/subscribers/entity-audit.subscriber.js +69 -5
- package/cache/cache.module.d.ts +7 -8
- package/cache/cache.module.js +15 -13
- package/cache/cache.service.d.ts +6 -4
- package/cache/cache.service.js +24 -12
- package/cache/decorators/cache-put.decorator.js +5 -4
- package/cache/dependencies/callback.dependency.js +9 -0
- package/cache/dependencies/db.dependency.d.ts +43 -12
- package/cache/dependencies/db.dependency.js +46 -18
- package/cache/dependencies/tag.dependency.d.ts +31 -4
- package/cache/dependencies/tag.dependency.js +100 -11
- package/cache/entities/index.d.ts +1 -0
- package/cache/entities/index.js +17 -0
- package/cache/entities/typeorm-cache.entity.d.ts +71 -0
- package/cache/entities/typeorm-cache.entity.js +110 -0
- package/cache/index.d.ts +2 -1
- package/cache/index.js +19 -2
- package/cache/interfaces/cache-options.interface.d.ts +8 -0
- package/cache/providers/index.d.ts +2 -1
- package/cache/providers/index.js +2 -1
- package/cache/providers/lrucache.provider.d.ts +77 -0
- package/cache/providers/lrucache.provider.js +228 -0
- package/cache/providers/redis-cache.provider.d.ts +1 -0
- package/cache/providers/redis-cache.provider.js +8 -6
- package/cache/providers/typeorm-cache.provider.d.ts +211 -0
- package/cache/providers/typeorm-cache.provider.js +483 -0
- package/common/boilerplate.polyfill.d.ts +1 -0
- package/common/boilerplate.polyfill.js +18 -1
- package/common/helpers/validation-metadata-helper.d.ts +112 -0
- package/common/helpers/validation-metadata-helper.js +164 -0
- package/common/index.d.ts +1 -0
- package/common/index.js +4 -0
- package/decorators/examples/field-i18n.example.d.ts +294 -0
- package/decorators/examples/field-i18n.example.js +478 -0
- package/decorators/field.decorators.d.ts +95 -3
- package/decorators/field.decorators.js +152 -18
- package/decorators/transform.decorators.d.ts +0 -2
- package/decorators/transform.decorators.js +0 -23
- package/decorators/translate.decorator.d.ts +26 -0
- package/decorators/translate.decorator.js +26 -1
- package/email-log/email-log.constants.d.ts +8 -0
- package/email-log/email-log.constants.js +11 -0
- package/email-log/email-log.module.d.ts +47 -0
- package/email-log/email-log.module.js +140 -0
- package/email-log/index.d.ts +11 -0
- package/email-log/index.js +48 -0
- package/email-log/interfaces/email-log-options.interface.d.ts +61 -0
- package/email-log/interfaces/email-log-options.interface.js +134 -0
- package/email-log/interfaces/email-log-transport.interface.d.ts +20 -0
- package/email-log/interfaces/email-log-transport.interface.js +2 -0
- package/email-log/interfaces/index.d.ts +2 -0
- package/email-log/interfaces/index.js +18 -0
- package/email-log/providers/email-provider.d.ts +42 -0
- package/email-log/providers/email-provider.js +127 -0
- package/email-log/providers/index.d.ts +1 -0
- package/email-log/providers/index.js +17 -0
- package/email-log/services/email-log-alert.service.d.ts +46 -0
- package/email-log/services/email-log-alert.service.js +162 -0
- package/email-log/services/email-log-formatter.service.d.ts +78 -0
- package/email-log/services/email-log-formatter.service.js +442 -0
- package/email-log/services/email-log-logger.service.d.ts +85 -0
- package/email-log/services/email-log-logger.service.js +168 -0
- package/email-log/services/email-log-rate-limiter.service.d.ts +42 -0
- package/email-log/services/email-log-rate-limiter.service.js +110 -0
- package/email-log/services/email-log-transport.service.d.ts +80 -0
- package/email-log/services/email-log-transport.service.js +271 -0
- package/email-log/services/index.d.ts +5 -0
- package/email-log/services/index.js +21 -0
- package/email-log/transports/index.d.ts +1 -0
- package/email-log/transports/index.js +17 -0
- package/email-log/transports/pino-email.transport.d.ts +56 -0
- package/email-log/transports/pino-email.transport.js +188 -0
- package/email-log/utils/index.d.ts +2 -0
- package/email-log/utils/index.js +18 -0
- package/email-log/utils/log-level.helper.d.ts +46 -0
- package/email-log/utils/log-level.helper.js +74 -0
- package/email-log/utils/pino-transport.utils.d.ts +135 -0
- package/email-log/utils/pino-transport.utils.js +238 -0
- package/file-upload/controllers/file-access.controller.d.ts +23 -0
- package/file-upload/controllers/file-access.controller.js +128 -0
- package/file-upload/decorators/column.decorator.d.ts +151 -0
- package/file-upload/decorators/column.decorator.js +273 -0
- package/file-upload/decorators/csv-data.decorator.d.ts +30 -0
- package/file-upload/decorators/csv-data.decorator.js +85 -0
- package/file-upload/decorators/csv-import.decorator.d.ts +34 -0
- package/file-upload/decorators/csv-import.decorator.js +24 -0
- package/file-upload/decorators/examples/column-mapping.example.d.ts +76 -0
- package/file-upload/decorators/examples/column-mapping.example.js +122 -0
- package/file-upload/decorators/excel-data.decorator.d.ts +30 -0
- package/file-upload/decorators/excel-data.decorator.js +85 -0
- package/file-upload/decorators/file-upload.decorator.d.ts +83 -0
- package/file-upload/decorators/file-upload.decorator.js +172 -0
- package/file-upload/decorators/index.d.ts +5 -0
- package/file-upload/decorators/index.js +38 -0
- package/file-upload/decorators/process.decorator.d.ts +40 -0
- package/file-upload/decorators/process.decorator.js +52 -0
- package/file-upload/decorators/validate-data.decorator.d.ts +91 -0
- package/file-upload/decorators/validate-data.decorator.js +39 -0
- package/file-upload/dto/create-file.dto.d.ts +24 -0
- package/file-upload/dto/create-file.dto.js +112 -0
- package/file-upload/dto/find-files.dto.d.ts +15 -0
- package/file-upload/dto/find-files.dto.js +76 -0
- package/file-upload/dto/index.d.ts +4 -0
- package/file-upload/dto/index.js +20 -0
- package/file-upload/dto/pagination.dto.d.ts +7 -0
- package/file-upload/dto/pagination.dto.js +39 -0
- package/file-upload/dto/update-file.dto.d.ts +15 -0
- package/file-upload/dto/update-file.dto.js +67 -0
- package/file-upload/entities/file-metadata.entity.d.ts +25 -0
- package/file-upload/entities/file-metadata.entity.js +76 -0
- package/file-upload/entities/file.entity.d.ts +114 -0
- package/file-upload/entities/file.entity.js +350 -0
- package/file-upload/entities/index.d.ts +2 -0
- package/file-upload/entities/index.js +18 -0
- package/file-upload/enums/file-type.enum.d.ts +72 -0
- package/file-upload/enums/file-type.enum.js +212 -0
- package/file-upload/exceptions/file-upload.exception.d.ts +57 -0
- package/file-upload/exceptions/file-upload.exception.js +120 -0
- package/file-upload/exceptions/index.d.ts +1 -0
- package/file-upload/exceptions/index.js +17 -0
- package/file-upload/file-upload.module.d.ts +89 -0
- package/file-upload/file-upload.module.js +292 -0
- package/file-upload/index.d.ts +37 -0
- package/file-upload/index.js +77 -0
- package/file-upload/interceptors/file-upload.interceptor.d.ts +101 -0
- package/file-upload/interceptors/file-upload.interceptor.js +594 -0
- package/file-upload/interceptors/index.d.ts +1 -0
- package/file-upload/interceptors/index.js +17 -0
- package/file-upload/interfaces/custom-file-type.interface.d.ts +72 -0
- package/file-upload/interfaces/custom-file-type.interface.js +2 -0
- package/file-upload/interfaces/file-buffer.interface.d.ts +72 -0
- package/file-upload/interfaces/file-buffer.interface.js +2 -0
- package/file-upload/interfaces/file-entity.interface.d.ts +142 -0
- package/file-upload/interfaces/file-entity.interface.js +28 -0
- package/file-upload/interfaces/file-metadata.interface.d.ts +21 -0
- package/file-upload/interfaces/file-metadata.interface.js +2 -0
- package/file-upload/interfaces/file-processor.interface.d.ts +93 -0
- package/file-upload/interfaces/file-processor.interface.js +2 -0
- package/file-upload/interfaces/file-upload-options.interface.d.ts +74 -0
- package/file-upload/interfaces/file-upload-options.interface.js +5 -0
- package/file-upload/interfaces/index.d.ts +7 -0
- package/file-upload/interfaces/index.js +24 -0
- package/file-upload/interfaces/processor-options.interface.d.ts +102 -0
- package/file-upload/interfaces/processor-options.interface.js +2 -0
- package/file-upload/interfaces/storage-provider.interface.d.ts +239 -0
- package/file-upload/interfaces/storage-provider.interface.js +2 -0
- package/file-upload/interfaces/upload-options.interface.d.ts +19 -0
- package/file-upload/interfaces/upload-options.interface.js +2 -0
- package/file-upload/processors/csv.processor.d.ts +98 -0
- package/file-upload/processors/csv.processor.js +391 -0
- package/file-upload/processors/excel.processor.d.ts +130 -0
- package/file-upload/processors/excel.processor.js +547 -0
- package/file-upload/processors/image.processor.d.ts +199 -0
- package/file-upload/processors/image.processor.js +377 -0
- package/file-upload/providers/index.d.ts +2 -0
- package/file-upload/providers/index.js +18 -0
- package/file-upload/providers/local-storage.provider.d.ts +98 -0
- package/file-upload/providers/local-storage.provider.js +484 -0
- package/file-upload/providers/s3-storage.provider.d.ts +87 -0
- package/file-upload/providers/s3-storage.provider.js +455 -0
- package/file-upload/services/file-signature-validator.service.d.ts +118 -0
- package/file-upload/services/file-signature-validator.service.js +376 -0
- package/file-upload/services/file.service.d.ts +193 -0
- package/file-upload/services/file.service.js +638 -0
- package/file-upload/services/index.d.ts +4 -0
- package/file-upload/services/index.js +20 -0
- package/file-upload/services/malicious-file-detector.service.d.ts +300 -0
- package/file-upload/services/malicious-file-detector.service.js +1234 -0
- package/file-upload/services/mime-registry.service.d.ts +47 -0
- package/file-upload/services/mime-registry.service.js +167 -0
- package/file-upload/utils/checksum.util.d.ts +28 -0
- package/file-upload/utils/checksum.util.js +65 -0
- package/file-upload/utils/dynamic-import.util.d.ts +54 -0
- package/file-upload/utils/dynamic-import.util.js +156 -0
- package/file-upload/utils/filename.util.d.ts +59 -0
- package/file-upload/utils/filename.util.js +184 -0
- package/file-upload/utils/filepath.util.d.ts +70 -0
- package/file-upload/utils/filepath.util.js +152 -0
- package/file-upload/utils/index.d.ts +4 -0
- package/file-upload/utils/index.js +20 -0
- package/filters/bad-request.filter.d.ts +9 -0
- package/filters/bad-request.filter.js +57 -16
- package/http-client/config/http-client.config.d.ts +5 -0
- package/http-client/config/http-client.config.js +27 -14
- package/http-client/decorators/http-client.decorators.d.ts +7 -28
- package/http-client/decorators/http-client.decorators.js +124 -99
- package/http-client/entities/http-log.entity.d.ts +0 -20
- package/http-client/entities/http-log.entity.js +1 -21
- package/http-client/examples/advanced-usage.example.d.ts +4 -5
- package/http-client/examples/advanced-usage.example.js +7 -59
- package/http-client/examples/axios-config-extended.example.d.ts +17 -0
- package/http-client/examples/axios-config-extended.example.js +311 -0
- package/http-client/examples/flexible-response-example.d.ts +28 -0
- package/http-client/examples/flexible-response-example.js +120 -0
- package/http-client/examples/index.d.ts +2 -0
- package/http-client/examples/index.js +2 -0
- package/http-client/examples/proxy-from-environment.example.d.ts +133 -0
- package/http-client/examples/proxy-from-environment.example.js +409 -0
- package/http-client/examples/ssl-certificate.example.d.ts +47 -0
- package/http-client/examples/ssl-certificate.example.js +432 -0
- package/http-client/http-client.module.d.ts +43 -2
- package/http-client/http-client.module.js +150 -90
- package/http-client/index.d.ts +1 -1
- package/http-client/interfaces/api-client-config.interface.d.ts +24 -103
- package/http-client/interfaces/http-client-config.interface.d.ts +137 -62
- package/http-client/services/api-client-registry.service.d.ts +8 -21
- package/http-client/services/api-client-registry.service.js +31 -282
- package/http-client/services/circuit-breaker.service.d.ts +69 -2
- package/http-client/services/circuit-breaker.service.js +185 -7
- package/http-client/services/http-client.service.d.ts +85 -23
- package/http-client/services/http-client.service.js +512 -168
- package/http-client/services/http-log-query.service.js +0 -13
- package/http-client/services/index.d.ts +0 -1
- package/http-client/services/index.js +0 -1
- package/http-client/services/logging.service.d.ts +69 -16
- package/http-client/services/logging.service.js +290 -170
- package/http-client/utils/call-stack-extractor.util.d.ts +26 -0
- package/http-client/utils/call-stack-extractor.util.js +35 -0
- package/http-client/utils/context-extractor.util.d.ts +2 -0
- package/http-client/utils/context-extractor.util.js +17 -3
- package/http-client/utils/curl-generator.util.js +2 -5
- package/http-client/utils/index.d.ts +2 -0
- package/http-client/utils/index.js +2 -0
- package/http-client/utils/proxy-environment.util.d.ts +42 -0
- package/http-client/utils/proxy-environment.util.js +154 -0
- package/http-client/utils/retry-recorder.util.d.ts +0 -4
- package/http-client/utils/retry-recorder.util.js +2 -27
- package/http-client/utils/sanitize.util.d.ts +58 -0
- package/http-client/utils/sanitize.util.js +188 -0
- package/http-client/utils/security-validator.util.d.ts +118 -0
- package/http-client/utils/security-validator.util.js +354 -0
- package/index.d.ts +4 -1
- package/index.js +6 -1
- package/interceptors/translation-interceptor.service.d.ts +7 -0
- package/interceptors/translation-interceptor.service.js +40 -8
- package/ip-filter/constants.d.ts +21 -0
- package/ip-filter/constants.js +24 -0
- package/ip-filter/decorators/index.d.ts +1 -0
- package/ip-filter/decorators/index.js +17 -0
- package/ip-filter/decorators/ip-filter.decorator.d.ts +58 -0
- package/ip-filter/decorators/ip-filter.decorator.js +79 -0
- package/ip-filter/guards/index.d.ts +1 -0
- package/ip-filter/guards/index.js +17 -0
- package/ip-filter/guards/ip-filter.guard.d.ts +62 -0
- package/ip-filter/guards/ip-filter.guard.js +174 -0
- package/ip-filter/index.d.ts +7 -0
- package/ip-filter/index.js +23 -0
- package/ip-filter/interfaces/index.d.ts +4 -0
- package/ip-filter/interfaces/index.js +20 -0
- package/ip-filter/interfaces/ip-filter-async-options.interface.d.ts +15 -0
- package/ip-filter/interfaces/ip-filter-async-options.interface.js +2 -0
- package/ip-filter/interfaces/ip-filter-metadata.interface.d.ts +26 -0
- package/ip-filter/interfaces/ip-filter-metadata.interface.js +2 -0
- package/ip-filter/interfaces/ip-filter-options.interface.d.ts +34 -0
- package/ip-filter/interfaces/ip-filter-options.interface.js +2 -0
- package/ip-filter/interfaces/ip-rule.interface.d.ts +36 -0
- package/ip-filter/interfaces/ip-rule.interface.js +2 -0
- package/ip-filter/ip-filter.module.d.ts +55 -0
- package/ip-filter/ip-filter.module.js +105 -0
- package/ip-filter/services/index.d.ts +1 -0
- package/ip-filter/services/index.js +17 -0
- package/ip-filter/services/ip-filter.service.d.ts +92 -0
- package/ip-filter/services/ip-filter.service.js +238 -0
- package/ip-filter/utils/index.d.ts +1 -0
- package/ip-filter/utils/index.js +17 -0
- package/ip-filter/utils/ip-utils.d.ts +61 -0
- package/ip-filter/utils/ip-utils.js +162 -0
- package/package.json +34 -29
- package/providers/context.provider.d.ts +9 -0
- package/providers/context.provider.js +13 -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/index.d.ts +2 -0
- package/redis-lock/index.js +5 -1
- package/redis-lock/lock-heartbeat.service.d.ts +80 -0
- package/redis-lock/lock-heartbeat.service.js +232 -0
- package/redis-lock/redis-lock.module.d.ts +6 -0
- package/redis-lock/redis-lock.module.js +136 -77
- package/redis-lock/redis-lock.service.d.ts +31 -0
- package/redis-lock/redis-lock.service.js +124 -17
- package/setup/bootstrap.setup.d.ts +2 -1
- package/setup/bootstrap.setup.js +3 -2
- package/setup/index.d.ts +1 -0
- package/setup/index.js +1 -0
- package/setup/run-in-mode.decorator.d.ts +56 -0
- package/setup/run-in-mode.decorator.js +92 -0
- package/setup/schedule.decorator.d.ts +1 -0
- package/setup/schedule.decorator.js +28 -13
- package/setup/worker.decorator.js +10 -1
- package/shared/index.d.ts +1 -1
- package/shared/index.js +1 -1
- package/shared/{serviceRegistryModule.js → service-registry.module.js} +28 -17
- package/shared/services/api-config.service.d.ts +41 -0
- package/shared/services/api-config.service.js +166 -8
- package/shared/services/index.d.ts +0 -1
- package/shared/services/index.js +0 -1
- package/validators/custom-validate.validator.d.ts +1 -0
- package/validators/custom-validate.validator.js +1 -0
- package/validators/file-mimetype.validator.d.ts +0 -2
- package/validators/file-mimetype.validator.js +4 -6
- package/validators/is-exists.validator.d.ts +15 -6
- package/validators/is-exists.validator.js +8 -7
- package/validators/is-unique.validator.d.ts +22 -7
- package/validators/is-unique.validator.js +41 -17
- package/vault/vault-config.service.js +1 -1
- package/cache/providers/memory-cache.provider.d.ts +0 -49
- package/cache/providers/memory-cache.provider.js +0 -197
- package/http-client/services/cache.service.d.ts +0 -76
- package/http-client/services/cache.service.js +0 -333
- package/shared/services/validator.service.d.ts +0 -3
- package/shared/services/validator.service.js +0 -20
- /package/shared/{serviceRegistryModule.d.ts → service-registry.module.d.ts} +0 -0
|
@@ -27,8 +27,6 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
27
27
|
const schedule_1 = require("@nestjs/schedule");
|
|
28
28
|
const setup_1 = require("@sentry/nestjs/setup");
|
|
29
29
|
const cache_1 = require("../cache");
|
|
30
|
-
const transactional_1 = require("@nestjs-cls/transactional");
|
|
31
|
-
const transactional_adapter_typeorm_1 = require("@nestjs-cls/transactional-adapter-typeorm");
|
|
32
30
|
const nestjs_i18n_1 = require("nestjs-i18n");
|
|
33
31
|
const health_checker_1 = require("../health-checker");
|
|
34
32
|
const nestjs_redis_1 = require("@songkeys/nestjs-redis");
|
|
@@ -38,9 +36,10 @@ const redis_lock_1 = require("../redis-lock");
|
|
|
38
36
|
const typeorm_2 = require("typeorm");
|
|
39
37
|
const vault_1 = require("../vault");
|
|
40
38
|
const validators_1 = require("../validators");
|
|
39
|
+
const transaction_1 = require("@nest-omni/transaction");
|
|
40
|
+
const email_log_1 = require("../email-log");
|
|
41
41
|
const providers = [
|
|
42
42
|
services_1.ApiConfigService,
|
|
43
|
-
services_1.ValidatorService,
|
|
44
43
|
services_1.GeneratorService,
|
|
45
44
|
services_1.TranslationService,
|
|
46
45
|
validators_1.IsExistsValidator,
|
|
@@ -61,19 +60,6 @@ const modules = [
|
|
|
61
60
|
expandVariables: false,
|
|
62
61
|
envFilePath: [process.env.ENV_FILE_PATH, process.env.BASE_ENV_FILE_PATH],
|
|
63
62
|
}),
|
|
64
|
-
nestjs_cls_1.ClsModule.forRoot({
|
|
65
|
-
global: true,
|
|
66
|
-
middleware: { mount: true, saveReq: true },
|
|
67
|
-
plugins: [
|
|
68
|
-
new transactional_1.ClsPluginTransactional({
|
|
69
|
-
imports: [typeorm_1.TypeOrmModule],
|
|
70
|
-
adapter: new transactional_adapter_typeorm_1.TransactionalAdapterTypeOrm({
|
|
71
|
-
dataSourceToken: typeorm_2.DataSource,
|
|
72
|
-
}),
|
|
73
|
-
enableTransactionProxy: true,
|
|
74
|
-
}),
|
|
75
|
-
],
|
|
76
|
-
}),
|
|
77
63
|
nestjs_pino_1.LoggerModule.forRootAsync({
|
|
78
64
|
inject: [services_1.ApiConfigService],
|
|
79
65
|
useFactory: (config) => config.pinoConfig,
|
|
@@ -101,10 +87,23 @@ const modules = [
|
|
|
101
87
|
}),
|
|
102
88
|
];
|
|
103
89
|
if (services_1.ApiConfigService.toBoolean(process.env.DB_ENABLED, true)) {
|
|
90
|
+
// 1. 首先导入 TransactionModule
|
|
91
|
+
modules.push(transaction_1.TransactionModule.forRoot());
|
|
92
|
+
// 2. 导入 TypeORM 模块,并在初始化后注册数据源
|
|
104
93
|
modules.push(typeorm_1.TypeOrmModule.forRootAsync({
|
|
105
94
|
inject: [services_1.ApiConfigService],
|
|
106
95
|
useFactory: (config) => config.typeormConfig,
|
|
107
96
|
}));
|
|
97
|
+
// 4. 配置 CLS 模块
|
|
98
|
+
modules.push(nestjs_cls_1.ClsModule.forRootAsync({
|
|
99
|
+
imports: [typeorm_1.TypeOrmModule],
|
|
100
|
+
useFactory(args) {
|
|
101
|
+
return {
|
|
102
|
+
middleware: { mount: true, saveReq: true },
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
global: true,
|
|
106
|
+
}));
|
|
108
107
|
}
|
|
109
108
|
if (services_1.ApiConfigService.toBoolean(process.env.BULL_ENABLED)) {
|
|
110
109
|
modules.push(bull_1.BullModule.forRootAsync({
|
|
@@ -128,7 +127,6 @@ if (services_1.ApiConfigService.toBoolean(process.env.CACHE_ENABLED)) {
|
|
|
128
127
|
return {
|
|
129
128
|
isGlobal: true,
|
|
130
129
|
redisClient,
|
|
131
|
-
dataSource,
|
|
132
130
|
memoryTtl: config.getNumber('CACHE_TTL'),
|
|
133
131
|
memoryNamespace: config.getString('CACHE_NAMESPACE', 'default'),
|
|
134
132
|
enableCompression: config.getBoolean('CACHE_COMPRESSION_ENABLED', false),
|
|
@@ -165,6 +163,19 @@ if (services_1.ApiConfigService.toBoolean(process.env.SCHEDULE_ENABLED) &&
|
|
|
165
163
|
if (services_1.ApiConfigService.toBoolean(process.env.SCHEDULE_ENABLED)) {
|
|
166
164
|
modules.push(schedule_1.ScheduleModule.forRoot());
|
|
167
165
|
}
|
|
166
|
+
// Email log transport for Pino
|
|
167
|
+
if (services_1.ApiConfigService.toBoolean(process.env.EMAIL_LOG_ENABLED, false)) {
|
|
168
|
+
modules.push(email_log_1.EmailLogModule.forRootAsync({
|
|
169
|
+
inject: [services_1.ApiConfigService],
|
|
170
|
+
useFactory: (config) => {
|
|
171
|
+
const emailConfig = config.emailLogConfig;
|
|
172
|
+
if (!emailConfig) {
|
|
173
|
+
throw new Error('EMAIL_LOG_ENABLED is true but emailLogConfig is null');
|
|
174
|
+
}
|
|
175
|
+
return emailConfig;
|
|
176
|
+
},
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
168
179
|
let ServiceRegistryModule = class ServiceRegistryModule {
|
|
169
180
|
};
|
|
170
181
|
exports.ServiceRegistryModule = ServiceRegistryModule;
|
|
@@ -5,6 +5,7 @@ import { Params } from 'nestjs-pino';
|
|
|
5
5
|
import { BullRootModuleOptions } from '@nestjs/bull/dist/interfaces/bull-module-options.interface';
|
|
6
6
|
import { AxiosProxyConfig } from 'axios';
|
|
7
7
|
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
|
|
8
|
+
import { PinoEmailTransport } from '../../email-log';
|
|
8
9
|
export declare class ApiConfigService {
|
|
9
10
|
private configService;
|
|
10
11
|
static rootPath: string;
|
|
@@ -47,7 +48,47 @@ export declare class ApiConfigService {
|
|
|
47
48
|
get isRedisEnabled(): boolean;
|
|
48
49
|
get bullConfig(): BullRootModuleOptions;
|
|
49
50
|
get pinoConfig(): Params;
|
|
51
|
+
/**
|
|
52
|
+
* Get Pino multistream configuration with email transport
|
|
53
|
+
* This method provides additional stream for email logging
|
|
54
|
+
* Usage: pass to LoggerModule or use with pino.multistream()
|
|
55
|
+
*/
|
|
56
|
+
get pinoEmailStream(): {
|
|
57
|
+
level: string;
|
|
58
|
+
stream: any;
|
|
59
|
+
};
|
|
50
60
|
get axiosProxyConfig(): AxiosProxyConfig | false;
|
|
61
|
+
/**
|
|
62
|
+
* Email log transport configuration
|
|
63
|
+
* Returns null if email logging is disabled
|
|
64
|
+
*/
|
|
65
|
+
get emailLogConfig(): {
|
|
66
|
+
enabled: boolean;
|
|
67
|
+
to: string[];
|
|
68
|
+
from: string;
|
|
69
|
+
level: string;
|
|
70
|
+
subjectPrefix: string;
|
|
71
|
+
smtpHost: string;
|
|
72
|
+
smtpPort: number;
|
|
73
|
+
smtpUsername: string;
|
|
74
|
+
smtpPassword: string;
|
|
75
|
+
smtpSecure: boolean;
|
|
76
|
+
smtpIgnoreTLSError: boolean;
|
|
77
|
+
rateLimitMaxEmails: number;
|
|
78
|
+
rateLimitWindowMs: number;
|
|
79
|
+
rateLimitBurstSize: number;
|
|
80
|
+
useHtmlFormat: boolean;
|
|
81
|
+
includeApps: string[];
|
|
82
|
+
excludeApps: string[];
|
|
83
|
+
includeErrors: string[];
|
|
84
|
+
excludeErrors: string[];
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Get Pino email transport instance
|
|
88
|
+
* This returns a Pino transport that can be used directly with Pino logger
|
|
89
|
+
* Usage: pino(transport) or add to multistream
|
|
90
|
+
*/
|
|
91
|
+
get pinoEmailTransport(): PinoEmailTransport;
|
|
51
92
|
static getRootPath(): string;
|
|
52
93
|
static toBoolean(value: string, defaultValue?: any): boolean;
|
|
53
94
|
getNumber(key: string, defaultValue?: number): number;
|
|
@@ -16,7 +16,9 @@ const config_1 = require("@nestjs/config");
|
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
17
|
const connect_redis_1 = require("connect-redis");
|
|
18
18
|
const ioredis_1 = require("ioredis");
|
|
19
|
+
const pino_1 = require("pino");
|
|
19
20
|
const common_2 = require("../../common");
|
|
21
|
+
const email_log_1 = require("../../email-log");
|
|
20
22
|
let ApiConfigService = ApiConfigService_1 = class ApiConfigService {
|
|
21
23
|
constructor(configService) {
|
|
22
24
|
this.configService = configService;
|
|
@@ -47,6 +49,7 @@ let ApiConfigService = ApiConfigService_1 = class ApiConfigService {
|
|
|
47
49
|
}
|
|
48
50
|
get typeormConfig() {
|
|
49
51
|
return {
|
|
52
|
+
name: 'default',
|
|
50
53
|
autoLoadEntities: true,
|
|
51
54
|
type: 'mysql',
|
|
52
55
|
host: this.getString('DB_HOST'),
|
|
@@ -56,7 +59,7 @@ let ApiConfigService = ApiConfigService_1 = class ApiConfigService {
|
|
|
56
59
|
password: this.getString('DB_PASSWORD'),
|
|
57
60
|
database: this.getString('DB_DATABASE'),
|
|
58
61
|
subscribers: [],
|
|
59
|
-
synchronize: this.isDev,
|
|
62
|
+
synchronize: this.getBoolean('DB_SYNCHRONIZE', this.isDev),
|
|
60
63
|
migrationsRun: true,
|
|
61
64
|
logging: this.getBoolean('DB_LOG_ENABLED'),
|
|
62
65
|
logger: this.isDev ? 'formatted-console' : 'simple-console',
|
|
@@ -203,15 +206,68 @@ let ApiConfigService = ApiConfigService_1 = class ApiConfigService {
|
|
|
203
206
|
};
|
|
204
207
|
}
|
|
205
208
|
get pinoConfig() {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
const emailConfig = this.emailLogConfig;
|
|
210
|
+
const emailEnabled = (emailConfig === null || emailConfig === void 0 ? void 0 : emailConfig.enabled) || false;
|
|
211
|
+
// For dev mode without email, use pino-pretty
|
|
212
|
+
if (this.isDev && !emailEnabled) {
|
|
213
|
+
return {
|
|
214
|
+
pinoHttp: {
|
|
215
|
+
genReqId: (req) => req.id,
|
|
216
|
+
transport: {
|
|
217
|
+
target: 'pino-pretty',
|
|
218
|
+
},
|
|
219
|
+
level: 'debug',
|
|
220
|
+
customLogLevel: function (res) {
|
|
221
|
+
if (res.statusCode >= 500)
|
|
222
|
+
return 'error';
|
|
223
|
+
if (res.statusCode >= 400)
|
|
224
|
+
return 'warn';
|
|
225
|
+
return 'info';
|
|
226
|
+
},
|
|
227
|
+
wrapSerializers: true,
|
|
228
|
+
customProps: (req, res) => {
|
|
229
|
+
return {
|
|
230
|
+
env: this.nodeEnv,
|
|
231
|
+
appName: this.getString('NAME'),
|
|
232
|
+
user: req === null || req === void 0 ? void 0 : req.user,
|
|
233
|
+
'req.body': req === null || req === void 0 ? void 0 : req.body,
|
|
234
|
+
'res.body': res === null || res === void 0 ? void 0 : res.body,
|
|
235
|
+
};
|
|
236
|
+
},
|
|
237
|
+
redact: {
|
|
238
|
+
paths: ['req.headers.authorization', 'req.headers.apikey', 'req.headers.cookie'],
|
|
239
|
+
remove: true,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
// For production or when email is enabled
|
|
245
|
+
// Prepare multistream targets
|
|
246
|
+
const streams = [
|
|
247
|
+
{
|
|
248
|
+
level: 'trace',
|
|
249
|
+
stream: process.stdout,
|
|
250
|
+
},
|
|
251
|
+
];
|
|
252
|
+
// Add email transport if enabled
|
|
253
|
+
if (emailEnabled && emailConfig) {
|
|
254
|
+
try {
|
|
255
|
+
// Create email transport
|
|
256
|
+
const emailTransport = new email_log_1.PinoEmailTransport(emailConfig);
|
|
257
|
+
streams.push({
|
|
258
|
+
level: emailConfig.level || 'error',
|
|
259
|
+
stream: emailTransport,
|
|
260
|
+
});
|
|
209
261
|
}
|
|
210
|
-
|
|
262
|
+
catch (error) {
|
|
263
|
+
console.error('Failed to create Pino email transport:', error);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
211
266
|
return {
|
|
212
267
|
pinoHttp: {
|
|
213
268
|
genReqId: (req) => req.id,
|
|
214
|
-
|
|
269
|
+
// Use multistream for combining console and email output
|
|
270
|
+
stream: pino_1.default.multistream(streams),
|
|
215
271
|
level: this.isDev ? 'debug' : 'info',
|
|
216
272
|
customLogLevel: function (res) {
|
|
217
273
|
if (res.statusCode >= 500)
|
|
@@ -222,21 +278,70 @@ let ApiConfigService = ApiConfigService_1 = class ApiConfigService {
|
|
|
222
278
|
},
|
|
223
279
|
wrapSerializers: true,
|
|
224
280
|
customProps: (req, res) => {
|
|
281
|
+
var _a, _b, _c, _d, _e;
|
|
282
|
+
// Get protocol, host and port from request
|
|
283
|
+
const protocol = req.protocol || 'http';
|
|
284
|
+
const hostHeader = req.get('host') || req.hostname || 'localhost';
|
|
285
|
+
const hostname = req.hostname || 'localhost';
|
|
286
|
+
const port = ((_a = req.socket) === null || _a === void 0 ? void 0 : _a.localPort) || this.appConfig.port || 3000;
|
|
287
|
+
// Build baseUrl - if host already includes port, don't add it again
|
|
288
|
+
const hasPortInHost = hostHeader.includes(':');
|
|
289
|
+
const baseUrl = hasPortInHost
|
|
290
|
+
? `${protocol}://${hostHeader}`
|
|
291
|
+
: `${protocol}://${hostHeader}:${port}`;
|
|
225
292
|
return {
|
|
226
293
|
env: this.nodeEnv,
|
|
227
294
|
appName: this.getString('NAME'),
|
|
295
|
+
// User information
|
|
228
296
|
user: req === null || req === void 0 ? void 0 : req.user,
|
|
229
|
-
|
|
297
|
+
// Request information (for email alerts)
|
|
298
|
+
request: req ? {
|
|
299
|
+
id: req.id,
|
|
300
|
+
method: req.method,
|
|
301
|
+
url: req.originalUrl || req.url,
|
|
302
|
+
query: req.query,
|
|
303
|
+
params: req.params,
|
|
304
|
+
body: req.body,
|
|
305
|
+
ip: req.ip,
|
|
306
|
+
protocol,
|
|
307
|
+
host: hostname,
|
|
308
|
+
port,
|
|
309
|
+
baseUrl,
|
|
310
|
+
headers: {
|
|
311
|
+
'user-agent': (_b = req.headers) === null || _b === void 0 ? void 0 : _b['user-agent'],
|
|
312
|
+
referer: ((_c = req.headers) === null || _c === void 0 ? void 0 : _c.referer) || ((_d = req.headers) === null || _d === void 0 ? void 0 : _d.referrer),
|
|
313
|
+
host: (_e = req.headers) === null || _e === void 0 ? void 0 : _e.host,
|
|
314
|
+
},
|
|
315
|
+
} : undefined,
|
|
316
|
+
// Response body
|
|
230
317
|
'res.body': res === null || res === void 0 ? void 0 : res.body,
|
|
231
318
|
};
|
|
232
319
|
},
|
|
233
320
|
redact: {
|
|
234
|
-
paths: ['req.headers.authorization', 'req.headers.apikey'],
|
|
321
|
+
paths: ['req.headers.authorization', 'req.headers.apikey', 'req.headers.cookie'],
|
|
235
322
|
remove: true,
|
|
236
323
|
},
|
|
237
324
|
},
|
|
238
325
|
};
|
|
239
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Get Pino multistream configuration with email transport
|
|
329
|
+
* This method provides additional stream for email logging
|
|
330
|
+
* Usage: pass to LoggerModule or use with pino.multistream()
|
|
331
|
+
*/
|
|
332
|
+
get pinoEmailStream() {
|
|
333
|
+
const emailConfig = this.emailLogConfig;
|
|
334
|
+
if (!emailConfig || !emailConfig.enabled) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
// Return stream configuration for email transport
|
|
338
|
+
// The actual stream will be attached by EmailLogModule
|
|
339
|
+
return {
|
|
340
|
+
level: emailConfig.level,
|
|
341
|
+
// This will be replaced with the actual EmailLogTransportService stream
|
|
342
|
+
stream: null,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
240
345
|
get axiosProxyConfig() {
|
|
241
346
|
if (!this.getBoolean('DIRECT_PROXY_ENABLED')) {
|
|
242
347
|
return false;
|
|
@@ -246,6 +351,59 @@ let ApiConfigService = ApiConfigService_1 = class ApiConfigService {
|
|
|
246
351
|
port: this.getNumber('DIRECT_PROXY_PORT'),
|
|
247
352
|
};
|
|
248
353
|
}
|
|
354
|
+
/**
|
|
355
|
+
* Email log transport configuration
|
|
356
|
+
* Returns null if email logging is disabled
|
|
357
|
+
*/
|
|
358
|
+
get emailLogConfig() {
|
|
359
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
360
|
+
if (!this.getBoolean('EMAIL_LOG_ENABLED', false)) {
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
enabled: true,
|
|
365
|
+
to: this.getString('EMAIL_LOG_TO')
|
|
366
|
+
.split(',')
|
|
367
|
+
.map((e) => e.trim())
|
|
368
|
+
.filter(Boolean),
|
|
369
|
+
from: this.getString('EMAIL_LOG_FROM'),
|
|
370
|
+
level: this.getString('EMAIL_LOG_LEVEL', 'error'),
|
|
371
|
+
subjectPrefix: this.getString('EMAIL_LOG_SUBJECT_PREFIX', '[Log Alert]'),
|
|
372
|
+
smtpHost: this.getString('EMAIL_LOG_SMTP_HOST'),
|
|
373
|
+
smtpPort: this.getNumber('EMAIL_LOG_SMTP_PORT', 587),
|
|
374
|
+
smtpUsername: this.getString('EMAIL_LOG_SMTP_USERNAME', ''),
|
|
375
|
+
smtpPassword: this.getString('EMAIL_LOG_SMTP_PASSWORD', ''),
|
|
376
|
+
smtpSecure: this.getBoolean('EMAIL_LOG_SMTP_SECURE', false),
|
|
377
|
+
smtpIgnoreTLSError: this.getBoolean('EMAIL_LOG_SMTP_IGNORE_TLS_ERROR', false),
|
|
378
|
+
rateLimitMaxEmails: this.getNumber('EMAIL_LOG_RATE_LIMIT_MAX_EMAILS', 10),
|
|
379
|
+
rateLimitWindowMs: this.getNumber('EMAIL_LOG_RATE_LIMIT_WINDOW_MS', 60000),
|
|
380
|
+
rateLimitBurstSize: this.getNumber('EMAIL_LOG_RATE_LIMIT_BURST_SIZE', 3),
|
|
381
|
+
useHtmlFormat: this.getBoolean('EMAIL_LOG_USE_HTML_FORMAT', true),
|
|
382
|
+
includeApps: ((_b = (_a = this.getString('EMAIL_LOG_INCLUDE_APPS', '')) === null || _a === void 0 ? void 0 : _a.split(',')) === null || _b === void 0 ? void 0 : _b.filter(Boolean)) || undefined,
|
|
383
|
+
excludeApps: ((_d = (_c = this.getString('EMAIL_LOG_EXCLUDE_APPS', '')) === null || _c === void 0 ? void 0 : _c.split(',')) === null || _d === void 0 ? void 0 : _d.filter(Boolean)) || undefined,
|
|
384
|
+
includeErrors: ((_f = (_e = this.getString('EMAIL_LOG_INCLUDE_ERRORS', '')) === null || _e === void 0 ? void 0 : _e.split(',')) === null || _f === void 0 ? void 0 : _f.filter(Boolean)) || undefined,
|
|
385
|
+
excludeErrors: ((_h = (_g = this.getString('EMAIL_LOG_EXCLUDE_ERRORS', '')) === null || _g === void 0 ? void 0 : _g.split(',')) === null || _h === void 0 ? void 0 : _h.filter(Boolean)) || undefined,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get Pino email transport instance
|
|
390
|
+
* This returns a Pino transport that can be used directly with Pino logger
|
|
391
|
+
* Usage: pino(transport) or add to multistream
|
|
392
|
+
*/
|
|
393
|
+
get pinoEmailTransport() {
|
|
394
|
+
const config = this.emailLogConfig;
|
|
395
|
+
if (!config) {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
// Create and return email transport
|
|
399
|
+
try {
|
|
400
|
+
return new email_log_1.PinoEmailTransport(config);
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
console.error('Failed to create Pino email transport:', error);
|
|
404
|
+
return null;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
249
407
|
static getRootPath() {
|
|
250
408
|
if (!ApiConfigService_1.rootPath) {
|
|
251
409
|
throw new Error(`rootPath is not set`);
|
package/shared/services/index.js
CHANGED
|
@@ -17,4 +17,3 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./api-config.service"), exports);
|
|
18
18
|
__exportStar(require("./generator.service"), exports);
|
|
19
19
|
__exportStar(require("./translation.service"), exports);
|
|
20
|
-
__exportStar(require("./validator.service"), exports);
|
|
@@ -5,8 +5,6 @@ export type FileMimetypeValidatorOptions = {
|
|
|
5
5
|
message?: string;
|
|
6
6
|
};
|
|
7
7
|
export declare class FileMimetypeValidator extends FileValidator<FileMimetypeValidatorOptions, IFile> {
|
|
8
|
-
private allowedMimetypes;
|
|
9
|
-
private message;
|
|
10
8
|
constructor(options: FileMimetypeValidatorOptions);
|
|
11
9
|
buildErrorMessage(): string;
|
|
12
10
|
isValid(file?: IFile): boolean;
|
|
@@ -5,17 +5,15 @@ const file_validator_interface_1 = require("@nestjs/common/pipes/file/file-valid
|
|
|
5
5
|
class FileMimetypeValidator extends file_validator_interface_1.FileValidator {
|
|
6
6
|
constructor(options) {
|
|
7
7
|
super(options);
|
|
8
|
-
this.allowedMimetypes = options.allowedMimetypes;
|
|
9
|
-
this.message = options.message;
|
|
10
8
|
}
|
|
11
9
|
buildErrorMessage() {
|
|
12
|
-
if (this.message) {
|
|
13
|
-
return this.message;
|
|
10
|
+
if (this.validationOptions.message) {
|
|
11
|
+
return this.validationOptions.message;
|
|
14
12
|
}
|
|
15
|
-
return `Invalid file type. Only ${this.allowedMimetypes.join(', ')} are allowed.`;
|
|
13
|
+
return `Invalid file type. Only ${this.validationOptions.allowedMimetypes.join(', ')} are allowed.`;
|
|
16
14
|
}
|
|
17
15
|
isValid(file) {
|
|
18
|
-
return this.allowedMimetypes.includes(file.mimetype);
|
|
16
|
+
return this.validationOptions.allowedMimetypes.includes(file.mimetype);
|
|
19
17
|
}
|
|
20
18
|
}
|
|
21
19
|
exports.FileMimetypeValidator = FileMimetypeValidator;
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { ValidationArguments, ValidationOptions, ValidatorConstraintInterface } from 'class-validator';
|
|
2
2
|
import type { EntitySchema, FindOptionsWhere, ObjectType } from 'typeorm';
|
|
3
|
-
import { TransactionHost } from '@nestjs-cls/transactional';
|
|
4
|
-
import { TransactionalAdapterTypeOrm } from '@nestjs-cls/transactional-adapter-typeorm';
|
|
5
3
|
export declare class IsExistsValidator implements ValidatorConstraintInterface {
|
|
6
|
-
|
|
7
|
-
constructor(transactionHost: TransactionHost<TransactionalAdapterTypeOrm>);
|
|
4
|
+
constructor();
|
|
8
5
|
/**
|
|
9
6
|
* 解析 Entity 引用,支持多种形式:
|
|
10
7
|
* 1. Entity 类直接引用
|
|
@@ -21,9 +18,21 @@ export declare class IsExistsValidator implements ValidatorConstraintInterface {
|
|
|
21
18
|
validate<E>(value: string, args: IExistsValidationArguments<E>): Promise<boolean>;
|
|
22
19
|
defaultMessage(args: ValidationArguments): string;
|
|
23
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* IsExists 配置选项
|
|
23
|
+
*/
|
|
24
|
+
export interface IsExistsOptions {
|
|
25
|
+
/**
|
|
26
|
+
* 数据源名称或 DataSource 实例
|
|
27
|
+
* 用于多数据源场景,指定使用哪个数据源进行验证
|
|
28
|
+
* 例如:'readonly', 'report', 或直接传入 DataSource 实例
|
|
29
|
+
*/
|
|
30
|
+
dataSource?: string;
|
|
31
|
+
}
|
|
24
32
|
type ExistsValidationConstraints<E> = [
|
|
25
|
-
ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string),
|
|
26
|
-
(validationArguments: ValidationArguments) => FindOptionsWhere<E
|
|
33
|
+
(ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string)),
|
|
34
|
+
(validationArguments: ValidationArguments) => FindOptionsWhere<E>,
|
|
35
|
+
IsExistsOptions?
|
|
27
36
|
];
|
|
28
37
|
interface IExistsValidationArguments<E> extends ValidationArguments {
|
|
29
38
|
constraints: ExistsValidationConstraints<E>;
|
|
@@ -23,11 +23,9 @@ exports.IsExists = IsExists;
|
|
|
23
23
|
const class_validator_1 = require("class-validator");
|
|
24
24
|
const nestjs_i18n_1 = require("nestjs-i18n");
|
|
25
25
|
const common_1 = require("@nestjs/common");
|
|
26
|
-
const
|
|
26
|
+
const transaction_1 = require("@nest-omni/transaction");
|
|
27
27
|
let IsExistsValidator = class IsExistsValidator {
|
|
28
|
-
constructor(
|
|
29
|
-
this.transactionHost = transactionHost;
|
|
30
|
-
}
|
|
28
|
+
constructor() { }
|
|
31
29
|
/**
|
|
32
30
|
* 解析 Entity 引用,支持多种形式:
|
|
33
31
|
* 1. Entity 类直接引用
|
|
@@ -88,10 +86,13 @@ let IsExistsValidator = class IsExistsValidator {
|
|
|
88
86
|
}
|
|
89
87
|
validate(value, args) {
|
|
90
88
|
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
const [entityRef, findCondition] = args.constraints;
|
|
89
|
+
const [entityRef, findCondition, options] = args.constraints;
|
|
92
90
|
// 解析 Entity 引用
|
|
93
91
|
const entityClass = this.resolveEntity(entityRef, args.property, args.object);
|
|
94
|
-
|
|
92
|
+
// 获取数据源(支持多数据源)
|
|
93
|
+
const dataSourceName = (options === null || options === void 0 ? void 0 : options.dataSource) || 'default';
|
|
94
|
+
const dataSource = (0, transaction_1.getDataSource)(dataSourceName);
|
|
95
|
+
const repository = dataSource.getRepository(entityClass);
|
|
95
96
|
args.value = value;
|
|
96
97
|
return ((yield repository.count({
|
|
97
98
|
where: findCondition(args),
|
|
@@ -106,7 +107,7 @@ exports.IsExistsValidator = IsExistsValidator;
|
|
|
106
107
|
exports.IsExistsValidator = IsExistsValidator = __decorate([
|
|
107
108
|
(0, common_1.Injectable)(),
|
|
108
109
|
(0, class_validator_1.ValidatorConstraint)({ name: 'isExists', async: true }),
|
|
109
|
-
__metadata("design:paramtypes", [
|
|
110
|
+
__metadata("design:paramtypes", [])
|
|
110
111
|
], IsExistsValidator);
|
|
111
112
|
function IsExists(constraints, validationOptions) {
|
|
112
113
|
return (object, propertyName) => {
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type { ValidationArguments, ValidationOptions, ValidatorConstraintInterface } from 'class-validator';
|
|
2
|
-
import { EntitySchema, FindOptionsWhere, ObjectType } from 'typeorm';
|
|
3
|
-
import { TransactionHost } from '@nestjs-cls/transactional';
|
|
4
|
-
import { TransactionalAdapterTypeOrm } from '@nestjs-cls/transactional-adapter-typeorm';
|
|
2
|
+
import type { EntitySchema, FindOptionsWhere, ObjectType } from 'typeorm';
|
|
5
3
|
export declare class IsUniqueValidator implements ValidatorConstraintInterface {
|
|
6
|
-
|
|
7
|
-
constructor(transactionHost: TransactionHost<TransactionalAdapterTypeOrm>);
|
|
4
|
+
constructor();
|
|
8
5
|
/**
|
|
9
6
|
* 解析 Entity 引用,支持多种形式:
|
|
10
7
|
* 1. Entity 类直接引用
|
|
@@ -21,9 +18,27 @@ export declare class IsUniqueValidator implements ValidatorConstraintInterface {
|
|
|
21
18
|
validate<E>(value: string, args: IUniqueValidationArguments<E>): Promise<boolean>;
|
|
22
19
|
defaultMessage(args: ValidationArguments): string;
|
|
23
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* IsUnique 配置选项
|
|
23
|
+
*/
|
|
24
|
+
export interface IsUniqueOptions {
|
|
25
|
+
/**
|
|
26
|
+
* 手动指定用于判断是否为新建的字段名
|
|
27
|
+
* 适用于视图(View)等没有主键的场景
|
|
28
|
+
* 例如:uniqueKeys: ['id'] 或 uniqueKeys: ['id', 'version']
|
|
29
|
+
*/
|
|
30
|
+
uniqueKeys?: string[];
|
|
31
|
+
/**
|
|
32
|
+
* 数据源名称或 DataSource 实例
|
|
33
|
+
* 用于多数据源场景,指定使用哪个数据源进行验证
|
|
34
|
+
* 例如:'readonly', 'report', 或直接传入 DataSource 实例
|
|
35
|
+
*/
|
|
36
|
+
dataSource?: string;
|
|
37
|
+
}
|
|
24
38
|
type UniqueValidationConstraints<E> = [
|
|
25
|
-
ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string),
|
|
26
|
-
(validationArguments: ValidationArguments) => FindOptionsWhere<E
|
|
39
|
+
(ObjectType<E> | EntitySchema<E> | string | (() => ObjectType<E> | EntitySchema<E> | string)),
|
|
40
|
+
(validationArguments: ValidationArguments) => FindOptionsWhere<E>,
|
|
41
|
+
IsUniqueOptions?
|
|
27
42
|
];
|
|
28
43
|
interface IUniqueValidationArguments<E> extends ValidationArguments {
|
|
29
44
|
constraints: UniqueValidationConstraints<E>;
|
|
@@ -23,11 +23,9 @@ exports.IsUnique = IsUnique;
|
|
|
23
23
|
const class_validator_1 = require("class-validator");
|
|
24
24
|
const nestjs_i18n_1 = require("nestjs-i18n");
|
|
25
25
|
const common_1 = require("@nestjs/common");
|
|
26
|
-
const
|
|
26
|
+
const transaction_1 = require("@nest-omni/transaction");
|
|
27
27
|
let IsUniqueValidator = class IsUniqueValidator {
|
|
28
|
-
constructor(
|
|
29
|
-
this.transactionHost = transactionHost;
|
|
30
|
-
}
|
|
28
|
+
constructor() { }
|
|
31
29
|
/**
|
|
32
30
|
* 解析 Entity 引用,支持多种形式:
|
|
33
31
|
* 1. Entity 类直接引用
|
|
@@ -84,40 +82,66 @@ let IsUniqueValidator = class IsUniqueValidator {
|
|
|
84
82
|
}
|
|
85
83
|
validate(value, args) {
|
|
86
84
|
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
-
const [entityRef, findCondition] = args.constraints;
|
|
85
|
+
const [entityRef, findCondition, options] = args.constraints;
|
|
88
86
|
// 解析 Entity 引用
|
|
89
87
|
const entityClass = this.resolveEntity(entityRef, args.property, args.object);
|
|
90
|
-
|
|
88
|
+
// 获取数据源(支持多数据源)
|
|
89
|
+
const dataSourceName = (options === null || options === void 0 ? void 0 : options.dataSource) || 'default';
|
|
90
|
+
const dataSource = (0, transaction_1.getDataSource)(dataSourceName);
|
|
91
|
+
const repository = dataSource.getRepository(entityClass);
|
|
91
92
|
args.value = value;
|
|
92
93
|
let exists;
|
|
93
94
|
const defCon = findCondition(args);
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
95
|
+
// 获取用于判断是否为新建的字段
|
|
96
|
+
// 优先级:手动配置的 uniqueKeys > 实体主键
|
|
97
|
+
let pkCols;
|
|
98
|
+
if ((options === null || options === void 0 ? void 0 : options.uniqueKeys) && options.uniqueKeys.length > 0) {
|
|
99
|
+
// 1. 使用手动指定的字段
|
|
100
|
+
pkCols = options.uniqueKeys;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// 2. 使用实体的主键
|
|
104
|
+
pkCols = repository.metadata.primaryColumns.map((column) => column.propertyName);
|
|
105
|
+
}
|
|
106
|
+
// 如果没有主键也没有 uniqueKeys,使用简化逻辑
|
|
107
|
+
// 查询条件本身表示唯一性,只要存在记录就不允许
|
|
108
|
+
if (pkCols.length === 0) {
|
|
109
|
+
const count = yield repository.count({ where: defCon });
|
|
110
|
+
exists = count < 1;
|
|
111
|
+
return exists;
|
|
112
|
+
}
|
|
113
|
+
// 修复:检查是否为新建记录
|
|
114
|
+
// 如果所有 uniqueKeys/主键都没有值(null/undefined),则为新建
|
|
115
|
+
const isNew = !pkCols.some((pk) => {
|
|
116
|
+
const pkValue = args.object[pk];
|
|
117
|
+
return pkValue !== null && pkValue !== undefined && pkValue !== '';
|
|
118
|
+
});
|
|
119
|
+
if (isNew) {
|
|
120
|
+
// 新建场景:简单检查是否存在相同值的记录
|
|
121
|
+
exists = (yield repository.count({ where: defCon })) < 1;
|
|
101
122
|
}
|
|
102
123
|
else {
|
|
124
|
+
// 更新场景:需要排除当前记录(通过主键对比)
|
|
103
125
|
const entities = yield repository
|
|
104
126
|
.createQueryBuilder()
|
|
105
127
|
.where(defCon)
|
|
106
|
-
.select(pkCols)
|
|
107
128
|
.limit(2)
|
|
108
|
-
.
|
|
129
|
+
.getMany();
|
|
109
130
|
const entityCount = entities.length;
|
|
110
131
|
if (entityCount === 1) {
|
|
132
|
+
// 只有一条记录,检查是否是当前记录本身
|
|
111
133
|
const entity = entities[0];
|
|
112
134
|
const oldPk = {};
|
|
113
135
|
const newPk = {};
|
|
114
|
-
pkCols.
|
|
136
|
+
pkCols.forEach((pk) => {
|
|
115
137
|
oldPk[pk] = entity[pk];
|
|
116
138
|
newPk[pk] = args.object[pk];
|
|
117
139
|
});
|
|
140
|
+
// 如果主键相同,说明是自己,允许(唯一)
|
|
118
141
|
exists = JSON.stringify(oldPk) === JSON.stringify(newPk);
|
|
119
142
|
}
|
|
120
143
|
else {
|
|
144
|
+
// 0条或多条记录
|
|
121
145
|
exists = entityCount < 1;
|
|
122
146
|
}
|
|
123
147
|
}
|
|
@@ -132,7 +156,7 @@ exports.IsUniqueValidator = IsUniqueValidator;
|
|
|
132
156
|
exports.IsUniqueValidator = IsUniqueValidator = __decorate([
|
|
133
157
|
(0, common_1.Injectable)(),
|
|
134
158
|
(0, class_validator_1.ValidatorConstraint)({ name: 'isUnique', async: true }),
|
|
135
|
-
__metadata("design:paramtypes", [
|
|
159
|
+
__metadata("design:paramtypes", [])
|
|
136
160
|
], IsUniqueValidator);
|
|
137
161
|
function IsUnique(constraints, validationOptions) {
|
|
138
162
|
return function (object, propertyName) {
|