@flusys/nestjs-shared 7.1.0 → 8.0.0-beta.1
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/classes/api-controller.class.d.ts +4 -4
- package/classes/api-service.class.d.ts +7 -7
- package/classes/disabled-event-bus.class.d.ts +1 -1
- package/classes/domain-event.publisher.d.ts +1 -1
- package/classes/event-bus.registry.d.ts +1 -1
- package/classes/event-transports/event-transport.registry.d.ts +1 -1
- package/classes/event-transports/index.d.ts +2 -2
- package/classes/event-transports/kafka-transport.optional.d.ts +1 -1
- package/classes/event-transports/memory-transport.d.ts +1 -1
- package/classes/event-transports/rabbitmq-transport.optional.d.ts +1 -1
- package/classes/hybrid-event-bus.class.d.ts +1 -1
- package/classes/index.d.ts +11 -11
- package/constants/index.d.ts +2 -2
- package/decorators/api-response.decorator.d.ts +1 -1
- package/decorators/current-user.decorator.d.ts +1 -1
- package/decorators/index.d.ts +6 -6
- package/decorators/require-permission.decorator.d.ts +1 -1
- package/dtos/filter-and-pagination.dto.d.ts +1 -1
- package/dtos/index.d.ts +6 -6
- package/entities/index.d.ts +3 -3
- package/enums/index.d.ts +3 -3
- package/exceptions/index.d.ts +2 -2
- package/fesm/470.js +2713 -0
- package/fesm/509.js +793 -0
- package/fesm/667.js +606 -0
- package/fesm/67.js +808 -0
- package/fesm/720.js +914 -0
- package/{cjs/classes/event-transports/rabbitmq-transport.optional.js → fesm/chunks/123.js} +78 -55
- package/fesm/{classes/event-transports/kafka-transport.optional.js → chunks/37.js} +74 -41
- package/fesm/classes/index.js +62 -12
- package/fesm/constants/index.js +445 -17
- package/fesm/decorators/index.js +341 -6
- package/fesm/dtos/index.js +23 -6
- package/fesm/entities/index.js +336 -3
- package/fesm/enums/index.js +57 -3
- package/fesm/exceptions/index.js +280 -2
- package/fesm/guards/index.js +1003 -3
- package/fesm/index.js +1524 -14
- package/fesm/interceptors/index.js +924 -5
- package/fesm/interfaces/index.js +57 -11
- package/fesm/middlewares/index.js +33 -1
- package/fesm/modules/index.js +432 -9
- package/fesm/runtime.js +134 -0
- package/fesm/utils/index.js +1045 -8
- package/filters/global-exception.filter.d.ts +1 -1
- package/filters/index.d.ts +1 -1
- package/guards/index.d.ts +3 -3
- package/guards/jwt-auth.guard.d.ts +1 -1
- package/guards/optional-jwt-auth.guard.d.ts +1 -1
- package/guards/permission.guard.d.ts +2 -2
- package/index.d.ts +14 -14
- package/interceptors/delete-empty-id-from-body.interceptor.d.ts +1 -1
- package/interceptors/idempotency.interceptor.d.ts +2 -2
- package/interceptors/index.d.ts +5 -5
- package/interceptors/response-meta.interceptor.d.ts +1 -1
- package/interceptors/set-user-field-on-body.interceptor.d.ts +1 -1
- package/interceptors/slug.interceptor.d.ts +2 -2
- package/interfaces/ai-assistant-adapter.interface.d.ts +1 -1
- package/interfaces/api.interface.d.ts +2 -2
- package/interfaces/datasource.interface.d.ts +1 -1
- package/interfaces/event-manager-adapter.interface.d.ts +2 -2
- package/interfaces/index.d.ts +11 -11
- package/interfaces/module-config.interface.d.ts +1 -1
- package/interfaces/notification-adapter.interface.d.ts +1 -1
- package/middlewares/index.d.ts +1 -1
- package/middlewares/logger.middleware.d.ts +2 -2
- package/modules/cache/cache.module.d.ts +1 -1
- package/modules/datasource/index.d.ts +1 -1
- package/modules/datasource/multi-tenant-datasource.service.d.ts +4 -4
- package/modules/event-bus/event-bus.explorer.d.ts +2 -2
- package/modules/event-bus/event-bus.module.d.ts +2 -2
- package/modules/event-bus/module-events.provider.d.ts +1 -1
- package/modules/index.d.ts +9 -9
- package/modules/shared-permission-cache/shared-permission-cache.service.d.ts +3 -3
- package/modules/utils/utils.service.d.ts +1 -1
- package/package.json +30 -44
- package/utils/index.d.ts +8 -8
- package/utils/permission-cache-key.util.d.ts +1 -1
- package/utils/query-helpers.util.d.ts +2 -2
- package/utils/request.util.d.ts +1 -1
- package/cjs/classes/api-controller.class.js +0 -728
- package/cjs/classes/api-controller.class.spec.js +0 -684
- package/cjs/classes/api-service.class.js +0 -631
- package/cjs/classes/api-service.class.spec.js +0 -1137
- package/cjs/classes/disabled-event-bus.class.js +0 -15
- package/cjs/classes/disabled-event-bus.class.spec.js +0 -40
- package/cjs/classes/domain-event.publisher.js +0 -76
- package/cjs/classes/domain-event.publisher.spec.js +0 -234
- package/cjs/classes/event-bus.registry.js +0 -68
- package/cjs/classes/event-bus.registry.spec.js +0 -141
- package/cjs/classes/event-transports/event-transport.registry.js +0 -41
- package/cjs/classes/event-transports/event-transport.registry.spec.js +0 -31
- package/cjs/classes/event-transports/index.js +0 -23
- package/cjs/classes/event-transports/kafka-transport.optional.js +0 -151
- package/cjs/classes/event-transports/kafka-transport.optional.spec.js +0 -198
- package/cjs/classes/event-transports/memory-transport.js +0 -53
- package/cjs/classes/event-transports/memory-transport.spec.js +0 -57
- package/cjs/classes/event-transports/rabbitmq-transport.optional.spec.js +0 -255
- package/cjs/classes/handle-custome-db.js +0 -37
- package/cjs/classes/handle-custome-db.spec.js +0 -82
- package/cjs/classes/hybrid-cache.class.js +0 -96
- package/cjs/classes/hybrid-cache.class.spec.js +0 -168
- package/cjs/classes/hybrid-event-bus.class.js +0 -281
- package/cjs/classes/hybrid-event-bus.class.spec.js +0 -218
- package/cjs/classes/index.js +0 -28
- package/cjs/classes/winston.logger.class.js +0 -274
- package/cjs/classes/winston.logger.class.spec.js +0 -330
- package/cjs/constants/index.js +0 -88
- package/cjs/constants/message-keys.js +0 -68
- package/cjs/constants/permissions.js +0 -307
- package/cjs/decorators/api-response.decorator.js +0 -52
- package/cjs/decorators/api-response.decorator.spec.js +0 -126
- package/cjs/decorators/current-user.decorator.js +0 -16
- package/cjs/decorators/current-user.decorator.spec.js +0 -74
- package/cjs/decorators/index.js +0 -23
- package/cjs/decorators/log-action.decorator.js +0 -149
- package/cjs/decorators/log-action.decorator.spec.js +0 -353
- package/cjs/decorators/on-domain-event.decorator.js +0 -13
- package/cjs/decorators/on-domain-event.decorator.spec.js +0 -50
- package/cjs/decorators/public.decorator.js +0 -13
- package/cjs/decorators/public.decorator.spec.js +0 -50
- package/cjs/decorators/require-permission.decorator.js +0 -32
- package/cjs/decorators/require-permission.decorator.spec.js +0 -147
- package/cjs/dtos/delete.dto.js +0 -92
- package/cjs/dtos/filter-and-pagination.dto.js +0 -164
- package/cjs/dtos/get-by-ids.dto.js +0 -65
- package/cjs/dtos/identity-response.dto.js +0 -108
- package/cjs/dtos/index.js +0 -23
- package/cjs/dtos/pagination.dto.js +0 -67
- package/cjs/dtos/response-payload.dto.js +0 -369
- package/cjs/entities/identity.js +0 -100
- package/cjs/entities/index.js +0 -20
- package/cjs/entities/raw-type.js +0 -4
- package/cjs/entities/user-root.js +0 -189
- package/cjs/enums/index.js +0 -20
- package/cjs/enums/notification-type.enum.js +0 -17
- package/cjs/enums/participant-status.enum.js +0 -17
- package/cjs/enums/recurrence-type.enum.js +0 -18
- package/cjs/exceptions/base-app.exception.js +0 -151
- package/cjs/exceptions/base-app.exception.spec.js +0 -157
- package/cjs/exceptions/index.js +0 -19
- package/cjs/exceptions/permission.exception.js +0 -56
- package/cjs/exceptions/permission.exception.spec.js +0 -82
- package/cjs/filters/global-exception.filter.js +0 -279
- package/cjs/filters/global-exception.filter.spec.js +0 -440
- package/cjs/filters/index.js +0 -18
- package/cjs/guards/index.js +0 -20
- package/cjs/guards/jwt-auth.guard.js +0 -75
- package/cjs/guards/jwt-auth.guard.spec.js +0 -75
- package/cjs/guards/optional-jwt-auth.guard.js +0 -67
- package/cjs/guards/optional-jwt-auth.guard.spec.js +0 -55
- package/cjs/guards/permission.guard.js +0 -179
- package/cjs/guards/permission.guard.spec.js +0 -373
- package/cjs/index.js +0 -31
- package/cjs/interceptors/delete-empty-id-from-body.interceptor.js +0 -40
- package/cjs/interceptors/delete-empty-id-from-body.interceptor.spec.js +0 -107
- package/cjs/interceptors/idempotency.interceptor.js +0 -96
- package/cjs/interceptors/idempotency.interceptor.spec.js +0 -116
- package/cjs/interceptors/index.js +0 -22
- package/cjs/interceptors/response-meta.interceptor.js +0 -47
- package/cjs/interceptors/response-meta.interceptor.spec.js +0 -89
- package/cjs/interceptors/set-user-field-on-body.interceptor.js +0 -60
- package/cjs/interceptors/set-user-field-on-body.interceptor.spec.js +0 -128
- package/cjs/interceptors/slug.interceptor.js +0 -75
- package/cjs/interceptors/slug.interceptor.spec.js +0 -110
- package/cjs/interfaces/ai-assistant-adapter.interface.js +0 -24
- package/cjs/interfaces/api.interface.js +0 -4
- package/cjs/interfaces/datasource.interface.js +0 -4
- package/cjs/interfaces/event-bus.interface.js +0 -4
- package/cjs/interfaces/event-manager-adapter.interface.js +0 -11
- package/cjs/interfaces/identity.interface.js +0 -4
- package/cjs/interfaces/index.js +0 -28
- package/cjs/interfaces/logged-user-info.interface.js +0 -6
- package/cjs/interfaces/module-config.interface.js +0 -4
- package/cjs/interfaces/notification-adapter.interface.js +0 -11
- package/cjs/interfaces/permission-sync-adapter.interface.js +0 -11
- package/cjs/interfaces/permission.interface.js +0 -4
- package/cjs/middlewares/index.js +0 -18
- package/cjs/middlewares/logger.middleware.js +0 -264
- package/cjs/middlewares/logger.middleware.spec.js +0 -462
- package/cjs/modules/cache/cache.module.js +0 -39
- package/cjs/modules/cache/cache.module.spec.js +0 -48
- package/cjs/modules/datasource/index.js +0 -18
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +0 -222
- package/cjs/modules/datasource/multi-tenant-datasource.service.spec.js +0 -381
- package/cjs/modules/event-bus/event-bus.explorer.js +0 -124
- package/cjs/modules/event-bus/event-bus.explorer.spec.js +0 -189
- package/cjs/modules/event-bus/event-bus.integration.spec.js +0 -253
- package/cjs/modules/event-bus/event-bus.module.js +0 -94
- package/cjs/modules/event-bus/event-bus.module.spec.js +0 -149
- package/cjs/modules/event-bus/module-events.provider.js +0 -39
- package/cjs/modules/event-bus/module-events.provider.spec.js +0 -56
- package/cjs/modules/index.js +0 -26
- package/cjs/modules/shared-permission-cache/shared-permission-cache.module.js +0 -32
- package/cjs/modules/shared-permission-cache/shared-permission-cache.service.js +0 -101
- package/cjs/modules/shared-permission-cache/shared-permission-cache.service.spec.js +0 -165
- package/cjs/modules/utils/utils.module.js +0 -32
- package/cjs/modules/utils/utils.service.js +0 -76
- package/cjs/modules/utils/utils.service.spec.js +0 -169
- package/cjs/utils/date-time.util.js +0 -94
- package/cjs/utils/date-time.util.spec.js +0 -84
- package/cjs/utils/event-pattern.util.js +0 -103
- package/cjs/utils/event-pattern.util.spec.js +0 -251
- package/cjs/utils/html-sanitizer.util.js +0 -64
- package/cjs/utils/html-sanitizer.util.spec.js +0 -76
- package/cjs/utils/index.js +0 -25
- package/cjs/utils/optional-module.util.js +0 -35
- package/cjs/utils/optional-module.util.spec.js +0 -14
- package/cjs/utils/permission-cache-key.util.js +0 -31
- package/cjs/utils/permission-cache-key.util.spec.js +0 -88
- package/cjs/utils/query-helpers.util.js +0 -60
- package/cjs/utils/query-helpers.util.spec.js +0 -209
- package/cjs/utils/request.util.js +0 -96
- package/cjs/utils/request.util.spec.js +0 -249
- package/cjs/utils/string.util.js +0 -63
- package/cjs/utils/string.util.spec.js +0 -63
- package/fesm/classes/api-controller.class.js +0 -718
- package/fesm/classes/api-controller.class.spec.js +0 -680
- package/fesm/classes/api-service.class.js +0 -621
- package/fesm/classes/api-service.class.spec.js +0 -1133
- package/fesm/classes/disabled-event-bus.class.js +0 -11
- package/fesm/classes/disabled-event-bus.class.spec.js +0 -36
- package/fesm/classes/domain-event.publisher.js +0 -63
- package/fesm/classes/domain-event.publisher.spec.js +0 -230
- package/fesm/classes/event-bus.registry.js +0 -64
- package/fesm/classes/event-bus.registry.spec.js +0 -137
- package/fesm/classes/event-transports/event-transport.registry.js +0 -35
- package/fesm/classes/event-transports/event-transport.registry.spec.js +0 -27
- package/fesm/classes/event-transports/index.js +0 -6
- package/fesm/classes/event-transports/kafka-transport.optional.spec.js +0 -194
- package/fesm/classes/event-transports/memory-transport.js +0 -49
- package/fesm/classes/event-transports/memory-transport.spec.js +0 -53
- package/fesm/classes/event-transports/rabbitmq-transport.optional.js +0 -174
- package/fesm/classes/event-transports/rabbitmq-transport.optional.spec.js +0 -251
- package/fesm/classes/handle-custome-db.js +0 -19
- package/fesm/classes/handle-custome-db.spec.js +0 -78
- package/fesm/classes/hybrid-cache.class.js +0 -81
- package/fesm/classes/hybrid-cache.class.spec.js +0 -164
- package/fesm/classes/hybrid-event-bus.class.js +0 -237
- package/fesm/classes/hybrid-event-bus.class.spec.js +0 -214
- package/fesm/classes/winston.logger.class.js +0 -228
- package/fesm/classes/winston.logger.class.spec.js +0 -327
- package/fesm/constants/message-keys.js +0 -49
- package/fesm/constants/permissions.js +0 -215
- package/fesm/decorators/api-response.decorator.js +0 -42
- package/fesm/decorators/api-response.decorator.spec.js +0 -122
- package/fesm/decorators/current-user.decorator.js +0 -18
- package/fesm/decorators/current-user.decorator.spec.js +0 -73
- package/fesm/decorators/log-action.decorator.js +0 -139
- package/fesm/decorators/log-action.decorator.spec.js +0 -349
- package/fesm/decorators/on-domain-event.decorator.js +0 -10
- package/fesm/decorators/on-domain-event.decorator.spec.js +0 -46
- package/fesm/decorators/public.decorator.js +0 -20
- package/fesm/decorators/public.decorator.spec.js +0 -46
- package/fesm/decorators/require-permission.decorator.js +0 -27
- package/fesm/decorators/require-permission.decorator.spec.js +0 -143
- package/fesm/dtos/delete.dto.js +0 -82
- package/fesm/dtos/filter-and-pagination.dto.js +0 -148
- package/fesm/dtos/get-by-ids.dto.js +0 -55
- package/fesm/dtos/identity-response.dto.js +0 -98
- package/fesm/dtos/pagination.dto.js +0 -57
- package/fesm/dtos/response-payload.dto.js +0 -336
- package/fesm/entities/identity.js +0 -90
- package/fesm/entities/raw-type.js +0 -1
- package/fesm/entities/user-root.js +0 -179
- package/fesm/enums/notification-type.enum.js +0 -7
- package/fesm/enums/participant-status.enum.js +0 -7
- package/fesm/enums/recurrence-type.enum.js +0 -8
- package/fesm/exceptions/base-app.exception.js +0 -115
- package/fesm/exceptions/base-app.exception.spec.js +0 -153
- package/fesm/exceptions/permission.exception.js +0 -35
- package/fesm/exceptions/permission.exception.spec.js +0 -78
- package/fesm/filters/global-exception.filter.js +0 -269
- package/fesm/filters/global-exception.filter.spec.js +0 -436
- package/fesm/filters/index.js +0 -1
- package/fesm/guards/jwt-auth.guard.js +0 -65
- package/fesm/guards/jwt-auth.guard.spec.js +0 -71
- package/fesm/guards/optional-jwt-auth.guard.js +0 -57
- package/fesm/guards/optional-jwt-auth.guard.spec.js +0 -51
- package/fesm/guards/permission.guard.js +0 -169
- package/fesm/guards/permission.guard.spec.js +0 -369
- package/fesm/interceptors/delete-empty-id-from-body.interceptor.js +0 -30
- package/fesm/interceptors/delete-empty-id-from-body.interceptor.spec.js +0 -103
- package/fesm/interceptors/idempotency.interceptor.js +0 -86
- package/fesm/interceptors/idempotency.interceptor.spec.js +0 -112
- package/fesm/interceptors/response-meta.interceptor.js +0 -37
- package/fesm/interceptors/response-meta.interceptor.spec.js +0 -85
- package/fesm/interceptors/set-user-field-on-body.interceptor.js +0 -39
- package/fesm/interceptors/set-user-field-on-body.interceptor.spec.js +0 -124
- package/fesm/interceptors/slug.interceptor.js +0 -65
- package/fesm/interceptors/slug.interceptor.spec.js +0 -106
- package/fesm/interfaces/ai-assistant-adapter.interface.js +0 -3
- package/fesm/interfaces/api.interface.js +0 -1
- package/fesm/interfaces/datasource.interface.js +0 -1
- package/fesm/interfaces/event-bus.interface.js +0 -1
- package/fesm/interfaces/event-manager-adapter.interface.js +0 -1
- package/fesm/interfaces/identity.interface.js +0 -1
- package/fesm/interfaces/logged-user-info.interface.js +0 -3
- package/fesm/interfaces/module-config.interface.js +0 -5
- package/fesm/interfaces/notification-adapter.interface.js +0 -1
- package/fesm/interfaces/permission-sync-adapter.interface.js +0 -1
- package/fesm/interfaces/permission.interface.js +0 -1
- package/fesm/middlewares/logger.middleware.js +0 -235
- package/fesm/middlewares/logger.middleware.spec.js +0 -459
- package/fesm/modules/cache/cache.module.js +0 -29
- package/fesm/modules/cache/cache.module.spec.js +0 -44
- package/fesm/modules/datasource/index.js +0 -1
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +0 -212
- package/fesm/modules/datasource/multi-tenant-datasource.service.spec.js +0 -377
- package/fesm/modules/event-bus/event-bus.explorer.js +0 -114
- package/fesm/modules/event-bus/event-bus.explorer.spec.js +0 -185
- package/fesm/modules/event-bus/event-bus.integration.spec.js +0 -249
- package/fesm/modules/event-bus/event-bus.module.js +0 -84
- package/fesm/modules/event-bus/event-bus.module.spec.js +0 -145
- package/fesm/modules/event-bus/module-events.provider.js +0 -26
- package/fesm/modules/event-bus/module-events.provider.spec.js +0 -52
- package/fesm/modules/shared-permission-cache/shared-permission-cache.module.js +0 -22
- package/fesm/modules/shared-permission-cache/shared-permission-cache.service.js +0 -91
- package/fesm/modules/shared-permission-cache/shared-permission-cache.service.spec.js +0 -161
- package/fesm/modules/utils/utils.module.js +0 -22
- package/fesm/modules/utils/utils.service.js +0 -66
- package/fesm/modules/utils/utils.service.spec.js +0 -165
- package/fesm/utils/date-time.util.js +0 -70
- package/fesm/utils/date-time.util.spec.js +0 -80
- package/fesm/utils/event-pattern.util.js +0 -91
- package/fesm/utils/event-pattern.util.spec.js +0 -247
- package/fesm/utils/html-sanitizer.util.js +0 -69
- package/fesm/utils/html-sanitizer.util.spec.js +0 -72
- package/fesm/utils/optional-module.util.js +0 -25
- package/fesm/utils/optional-module.util.spec.js +0 -10
- package/fesm/utils/permission-cache-key.util.js +0 -10
- package/fesm/utils/permission-cache-key.util.spec.js +0 -84
- package/fesm/utils/query-helpers.util.js +0 -85
- package/fesm/utils/query-helpers.util.spec.js +0 -205
- package/fesm/utils/request.util.js +0 -81
- package/fesm/utils/request.util.spec.js +0 -245
- package/fesm/utils/string.util.js +0 -71
- package/fesm/utils/string.util.spec.js +0 -59
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
function _define_property(obj, key, value) {
|
|
2
|
-
if (key in obj) {
|
|
3
|
-
Object.defineProperty(obj, key, {
|
|
4
|
-
value: value,
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true
|
|
8
|
-
});
|
|
9
|
-
} else {
|
|
10
|
-
obj[key] = value;
|
|
11
|
-
}
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
14
|
-
import { HttpException, HttpStatus } from '@nestjs/common';
|
|
15
|
-
import { ERROR_MESSAGES } from '../constants/message-keys';
|
|
16
|
-
export class BaseAppException extends HttpException {
|
|
17
|
-
constructor(options){
|
|
18
|
-
const status = options.status || HttpStatus.BAD_REQUEST;
|
|
19
|
-
super({
|
|
20
|
-
success: false,
|
|
21
|
-
message: options.message,
|
|
22
|
-
messageKey: options.messageKey || ERROR_MESSAGES.GENERIC,
|
|
23
|
-
messageVariables: options.messageVariables,
|
|
24
|
-
errors: options.errors
|
|
25
|
-
}, status), _define_property(this, "messageKey", void 0), _define_property(this, "messageVariables", void 0), _define_property(this, "errors", void 0), _define_property(this, "metadata", void 0);
|
|
26
|
-
this.messageKey = options.messageKey || ERROR_MESSAGES.GENERIC;
|
|
27
|
-
this.messageVariables = options.messageVariables;
|
|
28
|
-
this.errors = options.errors;
|
|
29
|
-
this.metadata = options.metadata;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
export class NotFoundException extends BaseAppException {
|
|
33
|
-
constructor(entity, id){
|
|
34
|
-
super({
|
|
35
|
-
message: id ? `${entity} with id "${id}" not found` : `${entity} not found`,
|
|
36
|
-
messageKey: ERROR_MESSAGES.NOT_FOUND,
|
|
37
|
-
status: HttpStatus.NOT_FOUND,
|
|
38
|
-
metadata: {
|
|
39
|
-
entity,
|
|
40
|
-
id
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export class ValidationException extends BaseAppException {
|
|
46
|
-
constructor(errors){
|
|
47
|
-
super({
|
|
48
|
-
message: 'Validation failed',
|
|
49
|
-
messageKey: ERROR_MESSAGES.VALIDATION,
|
|
50
|
-
status: HttpStatus.BAD_REQUEST,
|
|
51
|
-
errors
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
export class UnauthorizedException extends BaseAppException {
|
|
56
|
-
constructor(message = 'Unauthorized access'){
|
|
57
|
-
super({
|
|
58
|
-
message,
|
|
59
|
-
messageKey: ERROR_MESSAGES.UNAUTHORIZED,
|
|
60
|
-
status: HttpStatus.UNAUTHORIZED
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
export class ForbiddenException extends BaseAppException {
|
|
65
|
-
constructor(message = 'Access forbidden'){
|
|
66
|
-
super({
|
|
67
|
-
message,
|
|
68
|
-
messageKey: ERROR_MESSAGES.FORBIDDEN,
|
|
69
|
-
status: HttpStatus.FORBIDDEN
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
export class ConflictException extends BaseAppException {
|
|
74
|
-
constructor(entity, field){
|
|
75
|
-
super({
|
|
76
|
-
message: field ? `${entity} with this ${field} already exists` : `${entity} already exists`,
|
|
77
|
-
messageKey: ERROR_MESSAGES.CONFLICT,
|
|
78
|
-
messageVariables: {
|
|
79
|
-
entity,
|
|
80
|
-
...field !== undefined && {
|
|
81
|
-
field
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
status: HttpStatus.CONFLICT,
|
|
85
|
-
metadata: {
|
|
86
|
-
entity,
|
|
87
|
-
field
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
export class InternalServerException extends BaseAppException {
|
|
93
|
-
constructor(message = 'Internal server error'){
|
|
94
|
-
super({
|
|
95
|
-
message,
|
|
96
|
-
messageKey: ERROR_MESSAGES.INTERNAL,
|
|
97
|
-
status: HttpStatus.INTERNAL_SERVER_ERROR
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
export class ServiceUnavailableException extends BaseAppException {
|
|
102
|
-
constructor(service){
|
|
103
|
-
super({
|
|
104
|
-
message: `${service} is temporarily unavailable`,
|
|
105
|
-
messageKey: ERROR_MESSAGES.SERVICE_UNAVAILABLE,
|
|
106
|
-
messageVariables: {
|
|
107
|
-
service
|
|
108
|
-
},
|
|
109
|
-
status: HttpStatus.SERVICE_UNAVAILABLE,
|
|
110
|
-
metadata: {
|
|
111
|
-
service
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { HttpStatus } from '@nestjs/common';
|
|
2
|
-
import { ERROR_MESSAGES } from '../constants/message-keys';
|
|
3
|
-
import { BaseAppException, ConflictException, ForbiddenException, InternalServerException, NotFoundException, ServiceUnavailableException, UnauthorizedException, ValidationException } from './base-app.exception';
|
|
4
|
-
describe('BaseAppException', ()=>{
|
|
5
|
-
it('should default status to BAD_REQUEST when not provided', ()=>{
|
|
6
|
-
const exception = new BaseAppException({
|
|
7
|
-
message: 'oops'
|
|
8
|
-
});
|
|
9
|
-
expect(exception.getStatus()).toBe(HttpStatus.BAD_REQUEST);
|
|
10
|
-
});
|
|
11
|
-
it('should default messageKey to ERROR_MESSAGES.GENERIC when not provided', ()=>{
|
|
12
|
-
const exception = new BaseAppException({
|
|
13
|
-
message: 'oops'
|
|
14
|
-
});
|
|
15
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.GENERIC);
|
|
16
|
-
});
|
|
17
|
-
it('should use the provided status, messageKey, messageVariables, errors, and metadata', ()=>{
|
|
18
|
-
const errors = [
|
|
19
|
-
{
|
|
20
|
-
field: 'name',
|
|
21
|
-
message: 'required'
|
|
22
|
-
}
|
|
23
|
-
];
|
|
24
|
-
const exception = new BaseAppException({
|
|
25
|
-
message: 'Invalid',
|
|
26
|
-
messageKey: 'custom.key',
|
|
27
|
-
messageVariables: {
|
|
28
|
-
foo: 'bar'
|
|
29
|
-
},
|
|
30
|
-
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
|
31
|
-
errors,
|
|
32
|
-
metadata: {
|
|
33
|
-
extra: true
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
expect(exception.getStatus()).toBe(HttpStatus.UNPROCESSABLE_ENTITY);
|
|
37
|
-
expect(exception.messageKey).toBe('custom.key');
|
|
38
|
-
expect(exception.messageVariables).toEqual({
|
|
39
|
-
foo: 'bar'
|
|
40
|
-
});
|
|
41
|
-
expect(exception.errors).toEqual(errors);
|
|
42
|
-
expect(exception.metadata).toEqual({
|
|
43
|
-
extra: true
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
it('should build an HttpException response body with success:false', ()=>{
|
|
47
|
-
const exception = new BaseAppException({
|
|
48
|
-
message: 'oops',
|
|
49
|
-
messageKey: 'k'
|
|
50
|
-
});
|
|
51
|
-
expect(exception.getResponse()).toEqual({
|
|
52
|
-
success: false,
|
|
53
|
-
message: 'oops',
|
|
54
|
-
messageKey: 'k',
|
|
55
|
-
messageVariables: undefined,
|
|
56
|
-
errors: undefined
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe('NotFoundException', ()=>{
|
|
60
|
-
it('should build a message with id when id is provided', ()=>{
|
|
61
|
-
const exception = new NotFoundException('User', 'uuid-1');
|
|
62
|
-
expect(exception.getStatus()).toBe(HttpStatus.NOT_FOUND);
|
|
63
|
-
expect(exception.message).toBe('User with id "uuid-1" not found');
|
|
64
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.NOT_FOUND);
|
|
65
|
-
expect(exception.metadata).toEqual({
|
|
66
|
-
entity: 'User',
|
|
67
|
-
id: 'uuid-1'
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
it('should build a message without id when id is omitted', ()=>{
|
|
71
|
-
const exception = new NotFoundException('User');
|
|
72
|
-
expect(exception.message).toBe('User not found');
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
describe('ValidationException', ()=>{
|
|
76
|
-
it('should carry the validation errors and BAD_REQUEST status', ()=>{
|
|
77
|
-
const errors = [
|
|
78
|
-
{
|
|
79
|
-
field: 'email',
|
|
80
|
-
message: 'invalid format'
|
|
81
|
-
}
|
|
82
|
-
];
|
|
83
|
-
const exception = new ValidationException(errors);
|
|
84
|
-
expect(exception.getStatus()).toBe(HttpStatus.BAD_REQUEST);
|
|
85
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.VALIDATION);
|
|
86
|
-
expect(exception.errors).toEqual(errors);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
describe('UnauthorizedException', ()=>{
|
|
90
|
-
it('should use the default message when none is provided', ()=>{
|
|
91
|
-
const exception = new UnauthorizedException();
|
|
92
|
-
expect(exception.getStatus()).toBe(HttpStatus.UNAUTHORIZED);
|
|
93
|
-
expect(exception.message).toBe('Unauthorized access');
|
|
94
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.UNAUTHORIZED);
|
|
95
|
-
});
|
|
96
|
-
it('should use a custom message when provided', ()=>{
|
|
97
|
-
const exception = new UnauthorizedException('Custom message');
|
|
98
|
-
expect(exception.message).toBe('Custom message');
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
describe('ForbiddenException', ()=>{
|
|
102
|
-
it('should default to "Access forbidden"', ()=>{
|
|
103
|
-
const exception = new ForbiddenException();
|
|
104
|
-
expect(exception.getStatus()).toBe(HttpStatus.FORBIDDEN);
|
|
105
|
-
expect(exception.message).toBe('Access forbidden');
|
|
106
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.FORBIDDEN);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
describe('ConflictException', ()=>{
|
|
110
|
-
it('should include the field in the message and metadata when provided', ()=>{
|
|
111
|
-
const exception = new ConflictException('User', 'email');
|
|
112
|
-
expect(exception.getStatus()).toBe(HttpStatus.CONFLICT);
|
|
113
|
-
expect(exception.message).toBe('User with this email already exists');
|
|
114
|
-
expect(exception.messageVariables).toEqual({
|
|
115
|
-
entity: 'User',
|
|
116
|
-
field: 'email'
|
|
117
|
-
});
|
|
118
|
-
expect(exception.metadata).toEqual({
|
|
119
|
-
entity: 'User',
|
|
120
|
-
field: 'email'
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
it('should omit the field when not provided', ()=>{
|
|
124
|
-
const exception = new ConflictException('User');
|
|
125
|
-
expect(exception.message).toBe('User already exists');
|
|
126
|
-
expect(exception.messageVariables).toEqual({
|
|
127
|
-
entity: 'User'
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
describe('InternalServerException', ()=>{
|
|
132
|
-
it('should default to "Internal server error"', ()=>{
|
|
133
|
-
const exception = new InternalServerException();
|
|
134
|
-
expect(exception.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
|
|
135
|
-
expect(exception.message).toBe('Internal server error');
|
|
136
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.INTERNAL);
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
describe('ServiceUnavailableException', ()=>{
|
|
140
|
-
it('should build a message including the service name', ()=>{
|
|
141
|
-
const exception = new ServiceUnavailableException('Email');
|
|
142
|
-
expect(exception.getStatus()).toBe(HttpStatus.SERVICE_UNAVAILABLE);
|
|
143
|
-
expect(exception.message).toBe('Email is temporarily unavailable');
|
|
144
|
-
expect(exception.messageKey).toBe(ERROR_MESSAGES.SERVICE_UNAVAILABLE);
|
|
145
|
-
expect(exception.messageVariables).toEqual({
|
|
146
|
-
service: 'Email'
|
|
147
|
-
});
|
|
148
|
-
expect(exception.metadata).toEqual({
|
|
149
|
-
service: 'Email'
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { ForbiddenException, InternalServerErrorException } from '@nestjs/common';
|
|
2
|
-
import { ERROR_MESSAGES } from '../constants/message-keys';
|
|
3
|
-
export class PermissionSystemUnavailableException extends InternalServerErrorException {
|
|
4
|
-
constructor(){
|
|
5
|
-
super({
|
|
6
|
-
success: false,
|
|
7
|
-
message: 'Permission system temporarily unavailable',
|
|
8
|
-
messageKey: ERROR_MESSAGES.PERMISSION_SYSTEM_UNAVAILABLE
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
export class InsufficientPermissionsException extends ForbiddenException {
|
|
13
|
-
constructor(missingPermissions, operator = 'AND'){
|
|
14
|
-
const messageKey = operator === 'OR' ? ERROR_MESSAGES.INSUFFICIENT_PERMISSIONS_OR : ERROR_MESSAGES.INSUFFICIENT_PERMISSIONS;
|
|
15
|
-
super({
|
|
16
|
-
success: false,
|
|
17
|
-
message: 'Insufficient permissions',
|
|
18
|
-
messageKey,
|
|
19
|
-
messageVariables: {
|
|
20
|
-
permissions: missingPermissions.join(', ')
|
|
21
|
-
},
|
|
22
|
-
missingPermissions,
|
|
23
|
-
operator
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export class NoPermissionsFoundException extends ForbiddenException {
|
|
28
|
-
constructor(){
|
|
29
|
-
super({
|
|
30
|
-
success: false,
|
|
31
|
-
message: 'No permissions found',
|
|
32
|
-
messageKey: ERROR_MESSAGES.NO_PERMISSIONS_FOUND
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { ForbiddenException, InternalServerErrorException } from '@nestjs/common';
|
|
2
|
-
import { ERROR_MESSAGES } from '../constants/message-keys';
|
|
3
|
-
import { InsufficientPermissionsException, NoPermissionsFoundException, PermissionSystemUnavailableException } from './permission.exception';
|
|
4
|
-
describe('permission exceptions', ()=>{
|
|
5
|
-
describe('PermissionSystemUnavailableException', ()=>{
|
|
6
|
-
it('should be an InternalServerErrorException with the expected response body', ()=>{
|
|
7
|
-
const exception = new PermissionSystemUnavailableException();
|
|
8
|
-
expect(exception).toBeInstanceOf(InternalServerErrorException);
|
|
9
|
-
expect(exception.getResponse()).toMatchObject({
|
|
10
|
-
success: false,
|
|
11
|
-
message: 'Permission system temporarily unavailable',
|
|
12
|
-
messageKey: ERROR_MESSAGES.PERMISSION_SYSTEM_UNAVAILABLE
|
|
13
|
-
});
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
describe('InsufficientPermissionsException', ()=>{
|
|
17
|
-
it('should default to AND operator and matching messageKey', ()=>{
|
|
18
|
-
const exception = new InsufficientPermissionsException([
|
|
19
|
-
'user.create',
|
|
20
|
-
'user.update'
|
|
21
|
-
]);
|
|
22
|
-
expect(exception).toBeInstanceOf(ForbiddenException);
|
|
23
|
-
expect(exception.getResponse()).toMatchObject({
|
|
24
|
-
success: false,
|
|
25
|
-
message: 'Insufficient permissions',
|
|
26
|
-
messageKey: ERROR_MESSAGES.INSUFFICIENT_PERMISSIONS,
|
|
27
|
-
messageVariables: {
|
|
28
|
-
permissions: 'user.create, user.update'
|
|
29
|
-
},
|
|
30
|
-
missingPermissions: [
|
|
31
|
-
'user.create',
|
|
32
|
-
'user.update'
|
|
33
|
-
],
|
|
34
|
-
operator: 'AND'
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
it('should use the OR messageKey when operator is OR', ()=>{
|
|
38
|
-
const exception = new InsufficientPermissionsException([
|
|
39
|
-
'admin',
|
|
40
|
-
'manager'
|
|
41
|
-
], 'OR');
|
|
42
|
-
expect(exception.getResponse()).toMatchObject({
|
|
43
|
-
messageKey: ERROR_MESSAGES.INSUFFICIENT_PERMISSIONS_OR,
|
|
44
|
-
operator: 'OR'
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
it('should join a single missing permission without a separator', ()=>{
|
|
48
|
-
const exception = new InsufficientPermissionsException([
|
|
49
|
-
'user.create'
|
|
50
|
-
]);
|
|
51
|
-
expect(exception.getResponse()).toMatchObject({
|
|
52
|
-
messageVariables: {
|
|
53
|
-
permissions: 'user.create'
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
it('should handle an empty missing-permissions list', ()=>{
|
|
58
|
-
const exception = new InsufficientPermissionsException([]);
|
|
59
|
-
expect(exception.getResponse()).toMatchObject({
|
|
60
|
-
messageVariables: {
|
|
61
|
-
permissions: ''
|
|
62
|
-
},
|
|
63
|
-
missingPermissions: []
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
describe('NoPermissionsFoundException', ()=>{
|
|
68
|
-
it('should be a ForbiddenException with the expected response body', ()=>{
|
|
69
|
-
const exception = new NoPermissionsFoundException();
|
|
70
|
-
expect(exception).toBeInstanceOf(ForbiddenException);
|
|
71
|
-
expect(exception.getResponse()).toMatchObject({
|
|
72
|
-
success: false,
|
|
73
|
-
message: 'No permissions found',
|
|
74
|
-
messageKey: ERROR_MESSAGES.NO_PERMISSIONS_FOUND
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
});
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
function _define_property(obj, key, value) {
|
|
2
|
-
if (key in obj) {
|
|
3
|
-
Object.defineProperty(obj, key, {
|
|
4
|
-
value: value,
|
|
5
|
-
enumerable: true,
|
|
6
|
-
configurable: true,
|
|
7
|
-
writable: true
|
|
8
|
-
});
|
|
9
|
-
} else {
|
|
10
|
-
obj[key] = value;
|
|
11
|
-
}
|
|
12
|
-
return obj;
|
|
13
|
-
}
|
|
14
|
-
function _ts_decorate(decorators, target, key, desc) {
|
|
15
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
16
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
17
|
-
else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
18
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
19
|
-
}
|
|
20
|
-
import { Catch, HttpException, HttpStatus, Logger } from '@nestjs/common';
|
|
21
|
-
import { QueryFailedError } from 'typeorm';
|
|
22
|
-
import { ERROR_MESSAGES } from '../constants/message-keys';
|
|
23
|
-
import { BaseAppException, ConflictException } from '../exceptions/base-app.exception';
|
|
24
|
-
import { getCompanyId, getRequestId, getTenantId, getUserId } from '../middlewares/logger.middleware';
|
|
25
|
-
export class GlobalExceptionFilter {
|
|
26
|
-
catch(exception, host) {
|
|
27
|
-
const ctx = host.switchToHttp();
|
|
28
|
-
const request = ctx.getRequest();
|
|
29
|
-
const response = ctx.getResponse();
|
|
30
|
-
const responseTime = Date.now() - (request._startTime || Date.now());
|
|
31
|
-
const requestId = getRequestId() || request.headers['x-request-id'] || 'no-request-id';
|
|
32
|
-
const { statusCode, errorResponse } = this.resolveException(exception, requestId, responseTime);
|
|
33
|
-
const logContext = {
|
|
34
|
-
requestId,
|
|
35
|
-
userId: getUserId(),
|
|
36
|
-
tenantId: getTenantId(),
|
|
37
|
-
companyId: getCompanyId(),
|
|
38
|
-
method: request.method,
|
|
39
|
-
url: request.originalUrl,
|
|
40
|
-
path: request.path,
|
|
41
|
-
statusCode,
|
|
42
|
-
duration: `${responseTime}ms`,
|
|
43
|
-
messageKey: errorResponse.messageKey
|
|
44
|
-
};
|
|
45
|
-
const logMessage = `Exception caught "HTTP/1.1" "${request.method}" "${request.originalUrl}" - ${statusCode} "${errorResponse.messageKey}" ${responseTime}ms | ${errorResponse.message}`;
|
|
46
|
-
if (statusCode >= 500) {
|
|
47
|
-
this.logger.error(logMessage, exception instanceof Error ? exception.stack : undefined, logContext);
|
|
48
|
-
} else if (statusCode >= 400) {
|
|
49
|
-
this.logger.warn(logMessage, logContext);
|
|
50
|
-
}
|
|
51
|
-
response.status(statusCode).json(errorResponse);
|
|
52
|
-
}
|
|
53
|
-
resolveException(exception, requestId, responseTime) {
|
|
54
|
-
const meta = {
|
|
55
|
-
requestId,
|
|
56
|
-
timestamp: new Date().toISOString(),
|
|
57
|
-
responseTime
|
|
58
|
-
};
|
|
59
|
-
if (exception instanceof BaseAppException) {
|
|
60
|
-
return {
|
|
61
|
-
statusCode: exception.getStatus(),
|
|
62
|
-
errorResponse: {
|
|
63
|
-
success: false,
|
|
64
|
-
message: exception.message,
|
|
65
|
-
messageKey: exception.messageKey,
|
|
66
|
-
messageVariables: exception.messageVariables,
|
|
67
|
-
errors: exception.errors,
|
|
68
|
-
_meta: meta
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
if (exception instanceof HttpException) {
|
|
73
|
-
const resolved = this.resolveHttpException(exception);
|
|
74
|
-
return {
|
|
75
|
-
statusCode: resolved.statusCode,
|
|
76
|
-
errorResponse: {
|
|
77
|
-
success: false,
|
|
78
|
-
message: resolved.message,
|
|
79
|
-
messageKey: resolved.messageKey,
|
|
80
|
-
messageVariables: resolved.messageVariables,
|
|
81
|
-
errors: resolved.errors,
|
|
82
|
-
_meta: meta
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
if (exception instanceof QueryFailedError) {
|
|
87
|
-
const resolved = this.resolveQueryFailedError(exception);
|
|
88
|
-
if (resolved) {
|
|
89
|
-
return {
|
|
90
|
-
statusCode: resolved.getStatus(),
|
|
91
|
-
errorResponse: {
|
|
92
|
-
success: false,
|
|
93
|
-
message: resolved.message,
|
|
94
|
-
messageKey: resolved.messageKey,
|
|
95
|
-
messageVariables: resolved.messageVariables,
|
|
96
|
-
_meta: meta
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
103
|
-
errorResponse: {
|
|
104
|
-
success: false,
|
|
105
|
-
message: 'Internal server error',
|
|
106
|
-
messageKey: ERROR_MESSAGES.INTERNAL,
|
|
107
|
-
_meta: meta
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
resolveHttpException(exception) {
|
|
112
|
-
const statusCode = exception.getStatus();
|
|
113
|
-
const response = exception.getResponse();
|
|
114
|
-
if (typeof response === 'string') {
|
|
115
|
-
return {
|
|
116
|
-
statusCode,
|
|
117
|
-
message: response,
|
|
118
|
-
messageKey: ERROR_MESSAGES.HTTP
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
if (typeof response === 'object' && response !== null) {
|
|
122
|
-
const obj = response;
|
|
123
|
-
if (Array.isArray(obj.message)) {
|
|
124
|
-
const errors = obj.message.map((msg)=>{
|
|
125
|
-
const [field, ...rest] = msg.split(' ');
|
|
126
|
-
return {
|
|
127
|
-
field: field || 'unknown',
|
|
128
|
-
message: rest.join(' ') || msg
|
|
129
|
-
};
|
|
130
|
-
});
|
|
131
|
-
return {
|
|
132
|
-
statusCode,
|
|
133
|
-
message: 'Validation failed',
|
|
134
|
-
messageKey: ERROR_MESSAGES.VALIDATION,
|
|
135
|
-
errors
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return {
|
|
139
|
-
statusCode,
|
|
140
|
-
message: String(obj.message || 'Unknown error'),
|
|
141
|
-
messageKey: String(obj.messageKey || ERROR_MESSAGES.HTTP),
|
|
142
|
-
messageVariables: obj.messageVariables,
|
|
143
|
-
errors: obj.errors
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
statusCode,
|
|
148
|
-
message: 'Unknown error',
|
|
149
|
-
messageKey: ERROR_MESSAGES.UNKNOWN
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
resolveQueryFailedError(exception) {
|
|
153
|
-
const dbError = exception;
|
|
154
|
-
const code = dbError.driverError?.code ?? dbError.code;
|
|
155
|
-
const number = dbError.driverError?.number ?? dbError.number;
|
|
156
|
-
const errno = dbError.driverError?.errno ?? dbError.errno;
|
|
157
|
-
const sqlMessage = dbError.driverError?.sqlMessage ?? '';
|
|
158
|
-
const detail = dbError.driverError?.detail ?? dbError.detail ?? '';
|
|
159
|
-
const table = dbError.driverError?.table ?? dbError.table ?? '';
|
|
160
|
-
const column = dbError.driverError?.column ?? dbError.column;
|
|
161
|
-
const pgField = detail.match(/Key \(([^)]+)\)/)?.[1] ?? column;
|
|
162
|
-
// DUPLICATE / UNIQUE VIOLATION
|
|
163
|
-
// PG: 23505 | MSSQL: 2627 (constraint), 2601 (index) | MySQL: ER_DUP_ENTRY / errno 1062
|
|
164
|
-
if (code === '23505' || number === 2627 || number === 2601 || code === 'ER_DUP_ENTRY' || errno === 1062) {
|
|
165
|
-
const mysqlTable = sqlMessage.match(/for key '([^'.]+)\./)?.[1];
|
|
166
|
-
const mysqlIndex = sqlMessage.match(/for key '(?:[^.]+\.)?([^']+)'/)?.[1];
|
|
167
|
-
const resolvedTable = table || mysqlTable || 'record';
|
|
168
|
-
const resolvedField = pgField ? this.toHumanReadable(pgField) : mysqlIndex ? this.toHumanReadable(mysqlIndex) : undefined;
|
|
169
|
-
return new ConflictException(this.toHumanReadable(resolvedTable), resolvedField);
|
|
170
|
-
}
|
|
171
|
-
// FOREIGN KEY VIOLATION
|
|
172
|
-
// PG: 23503 | MSSQL: 547 | MySQL: ER_NO_REFERENCED_ROW_2/1452 (insert), ER_ROW_IS_REFERENCED_2/1451 (delete)
|
|
173
|
-
if (code === '23503' || number === 547 || code === 'ER_NO_REFERENCED_ROW_2' || code === 'ER_ROW_IS_REFERENCED_2' || errno === 1452 || errno === 1451) {
|
|
174
|
-
const mysqlColumn = sqlMessage.match(/FOREIGN KEY \(`([^`]+)`\)/)?.[1];
|
|
175
|
-
const raw = pgField ?? mysqlColumn;
|
|
176
|
-
const humanField = raw ? this.toHumanReadable(raw) : undefined;
|
|
177
|
-
return new BaseAppException({
|
|
178
|
-
message: humanField ? `Invalid reference for '${humanField}'` : 'Invalid reference',
|
|
179
|
-
messageKey: ERROR_MESSAGES.DB_FOREIGN_KEY,
|
|
180
|
-
messageVariables: humanField ? {
|
|
181
|
-
field: humanField
|
|
182
|
-
} : undefined,
|
|
183
|
-
status: HttpStatus.BAD_REQUEST
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
// NOT NULL VIOLATION
|
|
187
|
-
// PG: 23502 | MSSQL: 515 | MySQL: ER_BAD_NULL_ERROR / errno 1048
|
|
188
|
-
if (code === '23502' || number === 515 || code === 'ER_BAD_NULL_ERROR' || errno === 1048) {
|
|
189
|
-
const mysqlColumn = sqlMessage.match(/Column '([^']+)' cannot be null/)?.[1];
|
|
190
|
-
const humanField = this.toHumanReadable(column ?? mysqlColumn ?? 'field');
|
|
191
|
-
return new BaseAppException({
|
|
192
|
-
message: `Required field '${humanField}' cannot be null`,
|
|
193
|
-
messageKey: ERROR_MESSAGES.DB_NOT_NULL,
|
|
194
|
-
messageVariables: {
|
|
195
|
-
field: humanField
|
|
196
|
-
},
|
|
197
|
-
status: HttpStatus.BAD_REQUEST
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
// INVALID INPUT SYNTAX — PostgreSQL only (MySQL silently coerces types)
|
|
201
|
-
if (code === '22P02') {
|
|
202
|
-
const typeMatch = exception.message.match(/invalid input syntax for(?:\s+type)?\s+(\w+)/i);
|
|
203
|
-
const type = typeMatch?.[1] ?? 'value';
|
|
204
|
-
const humanField = column ? this.toHumanReadable(column) : undefined;
|
|
205
|
-
return new BaseAppException({
|
|
206
|
-
message: humanField ? `Invalid ${type} value for '${humanField}'` : `Invalid ${type} value`,
|
|
207
|
-
messageKey: ERROR_MESSAGES.DB_INVALID_INPUT,
|
|
208
|
-
messageVariables: {
|
|
209
|
-
type,
|
|
210
|
-
...humanField !== undefined && {
|
|
211
|
-
field: humanField
|
|
212
|
-
}
|
|
213
|
-
},
|
|
214
|
-
status: HttpStatus.BAD_REQUEST
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
// VALUE TOO LONG
|
|
218
|
-
// PG: 22001 | MySQL: ER_DATA_TOO_LONG / errno 1406
|
|
219
|
-
if (code === '22001' || code === 'ER_DATA_TOO_LONG' || errno === 1406) {
|
|
220
|
-
const mysqlColumn = sqlMessage.match(/Data too long for column '([^']+)'/)?.[1];
|
|
221
|
-
const resolvedColumn = column ?? mysqlColumn;
|
|
222
|
-
const humanField = resolvedColumn ? this.toHumanReadable(resolvedColumn) : undefined;
|
|
223
|
-
return new BaseAppException({
|
|
224
|
-
message: humanField ? `Value too long for '${humanField}'` : 'Value exceeds maximum length',
|
|
225
|
-
messageKey: ERROR_MESSAGES.DB_VALUE_TOO_LONG,
|
|
226
|
-
messageVariables: humanField !== undefined ? {
|
|
227
|
-
field: humanField
|
|
228
|
-
} : undefined,
|
|
229
|
-
status: HttpStatus.BAD_REQUEST
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
// CHECK CONSTRAINT VIOLATION
|
|
233
|
-
// PG: 23514 | MySQL 8.0+: ER_CHECK_CONSTRAINT_VIOLATED / errno 3819
|
|
234
|
-
if (code === '23514' || code === 'ER_CHECK_CONSTRAINT_VIOLATED' || errno === 3819) {
|
|
235
|
-
const constraint = dbError.driverError?.constraint ?? dbError.constraint;
|
|
236
|
-
const humanTable = this.toHumanReadable(table || 'record');
|
|
237
|
-
return new BaseAppException({
|
|
238
|
-
message: `${humanTable} violates a validation rule`,
|
|
239
|
-
messageKey: ERROR_MESSAGES.DB_CHECK_CONSTRAINT,
|
|
240
|
-
messageVariables: {
|
|
241
|
-
entity: humanTable,
|
|
242
|
-
...constraint !== undefined && {
|
|
243
|
-
constraint
|
|
244
|
-
}
|
|
245
|
-
},
|
|
246
|
-
status: HttpStatus.BAD_REQUEST
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
// DEADLOCK
|
|
250
|
-
// PG: 40P01 | MSSQL: 1205 | MySQL: ER_LOCK_DEADLOCK / errno 1213
|
|
251
|
-
if (code === '40P01' || number === 1205 || code === 'ER_LOCK_DEADLOCK' || errno === 1213) {
|
|
252
|
-
return new BaseAppException({
|
|
253
|
-
message: 'The request could not be completed due to a conflict, please try again',
|
|
254
|
-
messageKey: ERROR_MESSAGES.DB_DEADLOCK,
|
|
255
|
-
status: HttpStatus.SERVICE_UNAVAILABLE
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
|
-
return null;
|
|
259
|
-
}
|
|
260
|
-
toHumanReadable(dbName) {
|
|
261
|
-
return dbName.split(', ').map((part)=>part.split('_').map((word)=>word.toLowerCase() === 'id' ? 'ID' : word.charAt(0).toUpperCase() + word.slice(1)).join(' ')).join(', ');
|
|
262
|
-
}
|
|
263
|
-
constructor(){
|
|
264
|
-
_define_property(this, "logger", new Logger('ExceptionFilter'));
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
GlobalExceptionFilter = _ts_decorate([
|
|
268
|
-
Catch()
|
|
269
|
-
], GlobalExceptionFilter);
|