@flusys/nestjs-shared 3.0.0 → 4.0.0-rc
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/README.md +160 -80
- package/cjs/classes/api-controller.class.js +26 -8
- package/cjs/classes/api-service.class.js +100 -17
- package/cjs/classes/winston-logger-adapter.class.js +15 -20
- package/cjs/classes/winston.logger.class.js +103 -70
- package/cjs/constants/index.js +1 -0
- package/cjs/constants/message-keys.js +80 -0
- package/cjs/constants/permissions.js +65 -11
- package/cjs/decorators/index.js +1 -0
- package/cjs/decorators/log-action.decorator.js +149 -0
- package/cjs/dtos/response-payload.dto.js +72 -0
- package/cjs/enums/index.js +20 -0
- package/cjs/enums/notification-type.enum.js +17 -0
- package/cjs/enums/participant-status.enum.js +17 -0
- package/cjs/enums/recurrence-type.enum.js +18 -0
- package/cjs/exceptions/base-app.exception.js +145 -0
- package/cjs/exceptions/index.js +1 -0
- package/cjs/exceptions/permission.exception.js +12 -8
- package/cjs/filters/global-exception.filter.js +167 -0
- package/cjs/filters/index.js +18 -0
- package/cjs/guards/jwt-auth.guard.js +4 -1
- package/cjs/guards/permission.guard.js +6 -13
- package/cjs/index.js +2 -0
- package/cjs/interceptors/idempotency.interceptor.js +1 -1
- package/cjs/interceptors/index.js +0 -1
- package/cjs/interfaces/event-manager-adapter.interface.js +11 -0
- package/cjs/interfaces/index.js +2 -0
- package/cjs/interfaces/logger.interface.js +1 -4
- package/cjs/interfaces/notification-adapter.interface.js +11 -0
- package/cjs/middlewares/logger.middleware.js +83 -26
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +33 -11
- package/cjs/modules/utils/utils.service.js +4 -20
- package/cjs/utils/index.js +0 -1
- package/cjs/utils/query-helpers.util.js +8 -1
- package/classes/api-controller.class.d.ts +1 -0
- package/classes/api-service.class.d.ts +5 -10
- package/classes/winston-logger-adapter.class.d.ts +12 -11
- package/classes/winston.logger.class.d.ts +1 -0
- package/constants/index.d.ts +1 -0
- package/constants/message-keys.d.ts +81 -0
- package/constants/permissions.d.ts +72 -0
- package/decorators/index.d.ts +1 -0
- package/decorators/log-action.decorator.d.ts +8 -0
- package/dtos/response-payload.dto.d.ts +8 -0
- package/enums/index.d.ts +3 -0
- package/enums/notification-type.enum.d.ts +6 -0
- package/enums/participant-status.enum.d.ts +6 -0
- package/enums/recurrence-type.enum.d.ts +7 -0
- package/exceptions/base-app.exception.d.ts +41 -0
- package/exceptions/index.d.ts +1 -0
- package/exceptions/permission.exception.d.ts +1 -1
- package/fesm/classes/api-controller.class.js +26 -8
- package/fesm/classes/api-service.class.js +101 -18
- package/fesm/classes/winston-logger-adapter.class.js +18 -44
- package/fesm/classes/winston.logger.class.js +100 -68
- package/fesm/constants/index.js +2 -0
- package/fesm/constants/message-keys.js +59 -0
- package/fesm/constants/permissions.js +51 -14
- package/fesm/decorators/index.js +1 -0
- package/fesm/decorators/log-action.decorator.js +139 -0
- package/fesm/dtos/response-payload.dto.js +72 -0
- package/fesm/enums/index.js +3 -0
- package/fesm/enums/notification-type.enum.js +7 -0
- package/fesm/enums/participant-status.enum.js +7 -0
- package/fesm/enums/recurrence-type.enum.js +8 -0
- package/fesm/exceptions/base-app.exception.js +109 -0
- package/fesm/exceptions/index.js +1 -0
- package/fesm/exceptions/permission.exception.js +15 -17
- package/fesm/filters/global-exception.filter.js +157 -0
- package/fesm/filters/index.js +1 -0
- package/fesm/guards/jwt-auth.guard.js +5 -2
- package/fesm/guards/permission.guard.js +8 -15
- package/fesm/index.js +2 -0
- package/fesm/interceptors/idempotency.interceptor.js +2 -2
- package/fesm/interceptors/index.js +0 -1
- package/fesm/interfaces/event-manager-adapter.interface.js +1 -0
- package/fesm/interfaces/index.js +2 -0
- package/fesm/interfaces/logger.interface.js +1 -4
- package/fesm/interfaces/notification-adapter.interface.js +1 -0
- package/fesm/middlewares/logger.middleware.js +83 -26
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +34 -12
- package/fesm/modules/utils/utils.service.js +5 -21
- package/fesm/utils/index.js +0 -1
- package/fesm/utils/query-helpers.util.js +8 -1
- package/filters/global-exception.filter.d.ts +10 -0
- package/filters/index.d.ts +1 -0
- package/guards/permission.guard.d.ts +1 -3
- package/index.d.ts +2 -0
- package/interceptors/index.d.ts +0 -1
- package/interfaces/event-manager-adapter.interface.d.ts +43 -0
- package/interfaces/index.d.ts +2 -0
- package/interfaces/logger.interface.d.ts +5 -5
- package/interfaces/notification-adapter.interface.d.ts +22 -0
- package/modules/datasource/multi-tenant-datasource.service.d.ts +1 -2
- package/modules/utils/utils.service.d.ts +0 -1
- package/package.json +7 -2
- package/utils/index.d.ts +0 -1
- package/cjs/interceptors/query-performance.interceptor.js +0 -66
- package/cjs/utils/error-handler.util.js +0 -90
- package/fesm/interceptors/query-performance.interceptor.js +0 -56
- package/fesm/utils/error-handler.util.js +0 -82
- package/interceptors/query-performance.interceptor.d.ts +0 -8
- package/utils/error-handler.util.d.ts +0 -19
|
@@ -86,6 +86,42 @@ export declare const FORM_RESULT_PERMISSIONS: {
|
|
|
86
86
|
readonly UPDATE: "form-result.update";
|
|
87
87
|
readonly DELETE: "form-result.delete";
|
|
88
88
|
};
|
|
89
|
+
export declare const EVENT_PERMISSIONS: {
|
|
90
|
+
readonly CREATE: "event.create";
|
|
91
|
+
readonly READ: "event.read";
|
|
92
|
+
readonly UPDATE: "event.update";
|
|
93
|
+
readonly DELETE: "event.delete";
|
|
94
|
+
};
|
|
95
|
+
export declare const EVENT_PARTICIPANT_PERMISSIONS: {
|
|
96
|
+
readonly CREATE: "event-participant.create";
|
|
97
|
+
readonly READ: "event-participant.read";
|
|
98
|
+
readonly UPDATE: "event-participant.update";
|
|
99
|
+
readonly DELETE: "event-participant.delete";
|
|
100
|
+
};
|
|
101
|
+
export declare const NOTIFICATION_PERMISSIONS: {
|
|
102
|
+
readonly CREATE: "notification.create";
|
|
103
|
+
readonly READ: "notification.read";
|
|
104
|
+
readonly UPDATE: "notification.update";
|
|
105
|
+
readonly DELETE: "notification.delete";
|
|
106
|
+
};
|
|
107
|
+
export declare const LANGUAGE_PERMISSIONS: {
|
|
108
|
+
readonly CREATE: "language.create";
|
|
109
|
+
readonly READ: "language.read";
|
|
110
|
+
readonly UPDATE: "language.update";
|
|
111
|
+
readonly DELETE: "language.delete";
|
|
112
|
+
};
|
|
113
|
+
export declare const TRANSLATION_KEY_PERMISSIONS: {
|
|
114
|
+
readonly CREATE: "translation-key.create";
|
|
115
|
+
readonly READ: "translation-key.read";
|
|
116
|
+
readonly UPDATE: "translation-key.update";
|
|
117
|
+
readonly DELETE: "translation-key.delete";
|
|
118
|
+
};
|
|
119
|
+
export declare const TRANSLATION_PERMISSIONS: {
|
|
120
|
+
readonly CREATE: "translation.create";
|
|
121
|
+
readonly READ: "translation.read";
|
|
122
|
+
readonly UPDATE: "translation.update";
|
|
123
|
+
readonly DELETE: "translation.delete";
|
|
124
|
+
};
|
|
89
125
|
export declare const PERMISSIONS: {
|
|
90
126
|
readonly USER: {
|
|
91
127
|
readonly CREATE: "user.create";
|
|
@@ -175,5 +211,41 @@ export declare const PERMISSIONS: {
|
|
|
175
211
|
readonly UPDATE: "form-result.update";
|
|
176
212
|
readonly DELETE: "form-result.delete";
|
|
177
213
|
};
|
|
214
|
+
readonly EVENT: {
|
|
215
|
+
readonly CREATE: "event.create";
|
|
216
|
+
readonly READ: "event.read";
|
|
217
|
+
readonly UPDATE: "event.update";
|
|
218
|
+
readonly DELETE: "event.delete";
|
|
219
|
+
};
|
|
220
|
+
readonly EVENT_PARTICIPANT: {
|
|
221
|
+
readonly CREATE: "event-participant.create";
|
|
222
|
+
readonly READ: "event-participant.read";
|
|
223
|
+
readonly UPDATE: "event-participant.update";
|
|
224
|
+
readonly DELETE: "event-participant.delete";
|
|
225
|
+
};
|
|
226
|
+
readonly NOTIFICATION: {
|
|
227
|
+
readonly CREATE: "notification.create";
|
|
228
|
+
readonly READ: "notification.read";
|
|
229
|
+
readonly UPDATE: "notification.update";
|
|
230
|
+
readonly DELETE: "notification.delete";
|
|
231
|
+
};
|
|
232
|
+
readonly LANGUAGE: {
|
|
233
|
+
readonly CREATE: "language.create";
|
|
234
|
+
readonly READ: "language.read";
|
|
235
|
+
readonly UPDATE: "language.update";
|
|
236
|
+
readonly DELETE: "language.delete";
|
|
237
|
+
};
|
|
238
|
+
readonly TRANSLATION_KEY: {
|
|
239
|
+
readonly CREATE: "translation-key.create";
|
|
240
|
+
readonly READ: "translation-key.read";
|
|
241
|
+
readonly UPDATE: "translation-key.update";
|
|
242
|
+
readonly DELETE: "translation-key.delete";
|
|
243
|
+
};
|
|
244
|
+
readonly TRANSLATION: {
|
|
245
|
+
readonly CREATE: "translation.create";
|
|
246
|
+
readonly READ: "translation.read";
|
|
247
|
+
readonly UPDATE: "translation.update";
|
|
248
|
+
readonly DELETE: "translation.delete";
|
|
249
|
+
};
|
|
178
250
|
};
|
|
179
251
|
export type PermissionCode = (typeof PERMISSIONS)[keyof typeof PERMISSIONS][keyof (typeof PERMISSIONS)[keyof typeof PERMISSIONS]];
|
package/decorators/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare class RequestMetaDto {
|
|
|
6
6
|
export declare class SingleResponseDto<T> {
|
|
7
7
|
success: boolean;
|
|
8
8
|
message: string;
|
|
9
|
+
messageKey?: string;
|
|
10
|
+
messageVariables?: Record<string, string | number>;
|
|
9
11
|
data?: T;
|
|
10
12
|
_meta?: RequestMetaDto;
|
|
11
13
|
}
|
|
@@ -20,6 +22,8 @@ export declare class PaginationMetaDto {
|
|
|
20
22
|
export declare class ListResponseDto<T> {
|
|
21
23
|
success: boolean;
|
|
22
24
|
message: string;
|
|
25
|
+
messageKey?: string;
|
|
26
|
+
messageVariables?: Record<string, string | number>;
|
|
23
27
|
data?: T[];
|
|
24
28
|
meta: PaginationMetaDto;
|
|
25
29
|
_meta?: RequestMetaDto;
|
|
@@ -32,6 +36,8 @@ export declare class BulkMetaDto {
|
|
|
32
36
|
export declare class BulkResponseDto<T> {
|
|
33
37
|
success: boolean;
|
|
34
38
|
message: string;
|
|
39
|
+
messageKey?: string;
|
|
40
|
+
messageVariables?: Record<string, string | number>;
|
|
35
41
|
data?: T[];
|
|
36
42
|
meta: BulkMetaDto;
|
|
37
43
|
_meta?: RequestMetaDto;
|
|
@@ -39,5 +45,7 @@ export declare class BulkResponseDto<T> {
|
|
|
39
45
|
export declare class MessageResponseDto {
|
|
40
46
|
success: boolean;
|
|
41
47
|
message: string;
|
|
48
|
+
messageKey?: string;
|
|
49
|
+
messageVariables?: Record<string, string | number>;
|
|
42
50
|
_meta?: RequestMetaDto;
|
|
43
51
|
}
|
package/enums/index.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { HttpException, HttpStatus } from '@nestjs/common';
|
|
2
|
+
export interface IValidationError {
|
|
3
|
+
field: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface IBaseAppExceptionOptions {
|
|
7
|
+
message: string;
|
|
8
|
+
messageKey?: string;
|
|
9
|
+
messageParams?: Record<string, unknown>;
|
|
10
|
+
status?: HttpStatus;
|
|
11
|
+
errors?: IValidationError[];
|
|
12
|
+
metadata?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export declare class BaseAppException extends HttpException {
|
|
15
|
+
readonly messageKey: string;
|
|
16
|
+
readonly messageParams?: Record<string, unknown>;
|
|
17
|
+
readonly errors?: IValidationError[];
|
|
18
|
+
readonly metadata?: Record<string, unknown>;
|
|
19
|
+
constructor(options: IBaseAppExceptionOptions);
|
|
20
|
+
}
|
|
21
|
+
export declare class NotFoundException extends BaseAppException {
|
|
22
|
+
constructor(entity: string, id?: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class ValidationException extends BaseAppException {
|
|
25
|
+
constructor(errors: IValidationError[]);
|
|
26
|
+
}
|
|
27
|
+
export declare class UnauthorizedException extends BaseAppException {
|
|
28
|
+
constructor(message?: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class ForbiddenException extends BaseAppException {
|
|
31
|
+
constructor(message?: string);
|
|
32
|
+
}
|
|
33
|
+
export declare class ConflictException extends BaseAppException {
|
|
34
|
+
constructor(entity: string, field?: string);
|
|
35
|
+
}
|
|
36
|
+
export declare class InternalServerException extends BaseAppException {
|
|
37
|
+
constructor(message?: string);
|
|
38
|
+
}
|
|
39
|
+
export declare class ServiceUnavailableException extends BaseAppException {
|
|
40
|
+
constructor(service: string);
|
|
41
|
+
}
|
package/exceptions/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ForbiddenException, InternalServerErrorException } from '@nestjs/common';
|
|
2
2
|
export declare class PermissionSystemUnavailableException extends InternalServerErrorException {
|
|
3
|
-
constructor(
|
|
3
|
+
constructor();
|
|
4
4
|
}
|
|
5
5
|
export declare class InsufficientPermissionsException extends ForbiddenException {
|
|
6
6
|
constructor(missingPermissions: string[], operator?: 'AND' | 'OR');
|
|
@@ -78,6 +78,8 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
78
78
|
return applyDecorators(...decorators);
|
|
79
79
|
}
|
|
80
80
|
/** Creates an API Controller with standardized CRUD endpoints (POST-only RPC pattern) */ export function createApiController(createDtoClass, updateDtoClass, responseDtoClass, options = {}) {
|
|
81
|
+
// Entity name for message keys (defaults to 'item')
|
|
82
|
+
const entityName = options.entityName ?? 'item';
|
|
81
83
|
// Determine if security is global (applies to all) or per-endpoint
|
|
82
84
|
const securityConfig = options.security;
|
|
83
85
|
const endpointKeys = [
|
|
@@ -114,7 +116,8 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
114
116
|
const data = plainToInstance(responseDtoClass, entity);
|
|
115
117
|
return {
|
|
116
118
|
success: true,
|
|
117
|
-
message:
|
|
119
|
+
message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} created successfully`,
|
|
120
|
+
messageKey: `${entityName}.create.success`,
|
|
118
121
|
data
|
|
119
122
|
};
|
|
120
123
|
}
|
|
@@ -123,7 +126,11 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
123
126
|
const data = entities.map((item)=>plainToInstance(responseDtoClass, item));
|
|
124
127
|
return {
|
|
125
128
|
success: true,
|
|
126
|
-
message: `${data.length}
|
|
129
|
+
message: `${data.length} ${entityName}s created successfully`,
|
|
130
|
+
messageKey: `${entityName}.create.many.success`,
|
|
131
|
+
messageVariables: {
|
|
132
|
+
count: data.length
|
|
133
|
+
},
|
|
127
134
|
data,
|
|
128
135
|
meta: {
|
|
129
136
|
count: data.length,
|
|
@@ -137,7 +144,8 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
137
144
|
const data = plainToInstance(responseDtoClass, entity);
|
|
138
145
|
return {
|
|
139
146
|
success: true,
|
|
140
|
-
message:
|
|
147
|
+
message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} retrieved successfully`,
|
|
148
|
+
messageKey: `${entityName}.get.success`,
|
|
141
149
|
data
|
|
142
150
|
};
|
|
143
151
|
}
|
|
@@ -146,7 +154,8 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
146
154
|
const data = plainToInstance(responseDtoClass, entity);
|
|
147
155
|
return {
|
|
148
156
|
success: true,
|
|
149
|
-
message:
|
|
157
|
+
message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)} updated successfully`,
|
|
158
|
+
messageKey: `${entityName}.update.success`,
|
|
150
159
|
data
|
|
151
160
|
};
|
|
152
161
|
}
|
|
@@ -155,7 +164,11 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
155
164
|
const data = plainToInstance(responseDtoClass, entities);
|
|
156
165
|
return {
|
|
157
166
|
success: true,
|
|
158
|
-
message: `${data.length}
|
|
167
|
+
message: `${data.length} ${entityName}s updated successfully`,
|
|
168
|
+
messageKey: `${entityName}.update.many.success`,
|
|
169
|
+
messageVariables: {
|
|
170
|
+
count: data.length
|
|
171
|
+
},
|
|
159
172
|
data,
|
|
160
173
|
meta: {
|
|
161
174
|
count: data.length,
|
|
@@ -172,7 +185,8 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
172
185
|
const totalPages = pageSize > 0 ? Math.ceil(result.total / pageSize) : 1;
|
|
173
186
|
return {
|
|
174
187
|
success: true,
|
|
175
|
-
message:
|
|
188
|
+
message: `${entityName.charAt(0).toUpperCase() + entityName.slice(1)}s retrieved successfully`,
|
|
189
|
+
messageKey: `${entityName}.get.all.success`,
|
|
176
190
|
data,
|
|
177
191
|
meta: {
|
|
178
192
|
total: result.total,
|
|
@@ -187,10 +201,14 @@ import { ApiResponseDto } from '../decorators/api-response.decorator';
|
|
|
187
201
|
async delete(deleteDto, user) {
|
|
188
202
|
await this.service.delete(deleteDto, user);
|
|
189
203
|
const count = Array.isArray(deleteDto.id) ? deleteDto.id.length : 1;
|
|
190
|
-
const action = deleteDto.type === 'restore' ? '
|
|
204
|
+
const action = deleteDto.type === 'restore' ? 'restore' : 'delete';
|
|
191
205
|
return {
|
|
192
206
|
success: true,
|
|
193
|
-
message: `${count}
|
|
207
|
+
message: `${count} ${entityName}${count > 1 ? 's' : ''} ${action}d successfully`,
|
|
208
|
+
messageKey: `${entityName}.${action}.success`,
|
|
209
|
+
messageVariables: {
|
|
210
|
+
count
|
|
211
|
+
}
|
|
194
212
|
};
|
|
195
213
|
}
|
|
196
214
|
constructor(service){
|
|
@@ -11,9 +11,20 @@ function _define_property(obj, key, value) {
|
|
|
11
11
|
}
|
|
12
12
|
return obj;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
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
|
+
function _ts_metadata(k, v) {
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
22
|
+
}
|
|
23
|
+
import { DeleteDto } from '../dtos';
|
|
24
|
+
import { InternalServerErrorException, NotFoundException } from '@nestjs/common';
|
|
25
|
+
import { SYSTEM_MESSAGES } from '../constants';
|
|
16
26
|
import { In } from 'typeorm';
|
|
27
|
+
import { LogAction } from '../decorators/log-action.decorator';
|
|
17
28
|
/** Generic API service with CRUD operations and caching support */ export class ApiService {
|
|
18
29
|
async insert(dto, user) {
|
|
19
30
|
return this.executeInTransaction('insert', async (qr)=>{
|
|
@@ -78,7 +89,10 @@ import { In } from 'typeorm';
|
|
|
78
89
|
output = await finalQuery.getMany();
|
|
79
90
|
}
|
|
80
91
|
const result = this.convertEntityListToResponseListDto(output, isRaw);
|
|
81
|
-
if (!result || !result.length) throw new NotFoundException(
|
|
92
|
+
if (!result || !result.length) throw new NotFoundException({
|
|
93
|
+
message: 'No Data Found',
|
|
94
|
+
messageKey: SYSTEM_MESSAGES.NOT_FOUND
|
|
95
|
+
});
|
|
82
96
|
return result;
|
|
83
97
|
} catch (error) {
|
|
84
98
|
if (error instanceof NotFoundException) {
|
|
@@ -109,7 +123,10 @@ import { In } from 'typeorm';
|
|
|
109
123
|
if (convertResult.length) result = convertResult[0];
|
|
110
124
|
} else {
|
|
111
125
|
output = await finalQuery.getOne();
|
|
112
|
-
if (!output) throw new NotFoundException(
|
|
126
|
+
if (!output) throw new NotFoundException({
|
|
127
|
+
message: 'No Data Found',
|
|
128
|
+
messageKey: SYSTEM_MESSAGES.NOT_FOUND
|
|
129
|
+
});
|
|
113
130
|
result = this.convertEntityToResponseDto(output, false);
|
|
114
131
|
}
|
|
115
132
|
if (this.isCacheable) {
|
|
@@ -199,7 +216,15 @@ import { In } from 'typeorm';
|
|
|
199
216
|
const parameters = rawSubQuery.getParameters();
|
|
200
217
|
const orderedValues = [];
|
|
201
218
|
const convertedQuery = countSql.replace(/:(\w+)/g, (_, key)=>{
|
|
202
|
-
if (!(key in parameters))
|
|
219
|
+
if (!(key in parameters)) {
|
|
220
|
+
throw new InternalServerErrorException({
|
|
221
|
+
message: `Missing parameter value for: ${key}`,
|
|
222
|
+
messageKey: SYSTEM_MESSAGES.MISSING_PARAMETER,
|
|
223
|
+
messageParams: {
|
|
224
|
+
key
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
203
228
|
orderedValues.push(parameters[key]);
|
|
204
229
|
return '?';
|
|
205
230
|
});
|
|
@@ -272,13 +297,14 @@ import { In } from 'typeorm';
|
|
|
272
297
|
async clearCacheForId(entities) {
|
|
273
298
|
await Promise.all(entities.map((item)=>this.utilsService.clearCache(this.entityName, this.cacheManager, item.id)));
|
|
274
299
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
300
|
+
handleError(error, _operation) {
|
|
301
|
+
if (error instanceof Error) {
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
throw new InternalServerErrorException({
|
|
305
|
+
message: typeof error === 'string' ? error : 'Unknown error',
|
|
306
|
+
messageKey: SYSTEM_MESSAGES.INTERNAL_ERROR
|
|
280
307
|
});
|
|
281
|
-
ErrorHandler.rethrowError(error);
|
|
282
308
|
}
|
|
283
309
|
/** Ensures value is always an array */ ensureArray(value) {
|
|
284
310
|
return Array.isArray(value) ? value : [
|
|
@@ -375,7 +401,10 @@ import { In } from 'typeorm';
|
|
|
375
401
|
id: d.id
|
|
376
402
|
}
|
|
377
403
|
});
|
|
378
|
-
if (!existing) throw new NotFoundException(
|
|
404
|
+
if (!existing) throw new NotFoundException({
|
|
405
|
+
message: 'No such entity data found for update! Please, Try Again.',
|
|
406
|
+
messageKey: SYSTEM_MESSAGES.NOT_FOUND
|
|
407
|
+
});
|
|
379
408
|
return Object.assign(existing, d);
|
|
380
409
|
}
|
|
381
410
|
delete d.id;
|
|
@@ -393,21 +422,75 @@ import { In } from 'typeorm';
|
|
|
393
422
|
async getEntityClass() {
|
|
394
423
|
return await this.repository.create();
|
|
395
424
|
}
|
|
396
|
-
constructor(entityName, repository, cacheManager, utilsService,
|
|
425
|
+
constructor(entityName, repository, cacheManager, utilsService, _loggerName, isCacheable = false, moduleName){
|
|
397
426
|
_define_property(this, "entityName", void 0);
|
|
398
427
|
_define_property(this, "repository", void 0);
|
|
399
428
|
_define_property(this, "cacheManager", void 0);
|
|
400
429
|
_define_property(this, "utilsService", void 0);
|
|
401
|
-
_define_property(this, "
|
|
430
|
+
_define_property(this, "_loggerName", void 0);
|
|
402
431
|
_define_property(this, "isCacheable", void 0);
|
|
403
|
-
_define_property(this, "
|
|
432
|
+
_define_property(this, "moduleName", void 0);
|
|
404
433
|
this.entityName = entityName;
|
|
405
434
|
this.repository = repository;
|
|
406
435
|
this.cacheManager = cacheManager;
|
|
407
436
|
this.utilsService = utilsService;
|
|
408
|
-
this.
|
|
437
|
+
this._loggerName = _loggerName;
|
|
409
438
|
this.isCacheable = isCacheable;
|
|
410
|
-
this.
|
|
411
|
-
this.logger = new Logger(loggerName);
|
|
439
|
+
this.moduleName = moduleName;
|
|
412
440
|
}
|
|
413
441
|
}
|
|
442
|
+
_ts_decorate([
|
|
443
|
+
LogAction({
|
|
444
|
+
action: 'create'
|
|
445
|
+
}),
|
|
446
|
+
_ts_metadata("design:type", Function),
|
|
447
|
+
_ts_metadata("design:paramtypes", [
|
|
448
|
+
typeof CreateDtoT === "undefined" ? Object : CreateDtoT,
|
|
449
|
+
Object
|
|
450
|
+
]),
|
|
451
|
+
_ts_metadata("design:returntype", Promise)
|
|
452
|
+
], ApiService.prototype, "insert", null);
|
|
453
|
+
_ts_decorate([
|
|
454
|
+
LogAction({
|
|
455
|
+
action: 'createMany'
|
|
456
|
+
}),
|
|
457
|
+
_ts_metadata("design:type", Function),
|
|
458
|
+
_ts_metadata("design:paramtypes", [
|
|
459
|
+
typeof Array === "undefined" ? Object : Array,
|
|
460
|
+
Object
|
|
461
|
+
]),
|
|
462
|
+
_ts_metadata("design:returntype", Promise)
|
|
463
|
+
], ApiService.prototype, "insertMany", null);
|
|
464
|
+
_ts_decorate([
|
|
465
|
+
LogAction({
|
|
466
|
+
action: 'update'
|
|
467
|
+
}),
|
|
468
|
+
_ts_metadata("design:type", Function),
|
|
469
|
+
_ts_metadata("design:paramtypes", [
|
|
470
|
+
typeof UpdateDtoT === "undefined" ? Object : UpdateDtoT,
|
|
471
|
+
Object
|
|
472
|
+
]),
|
|
473
|
+
_ts_metadata("design:returntype", Promise)
|
|
474
|
+
], ApiService.prototype, "update", null);
|
|
475
|
+
_ts_decorate([
|
|
476
|
+
LogAction({
|
|
477
|
+
action: 'updateMany'
|
|
478
|
+
}),
|
|
479
|
+
_ts_metadata("design:type", Function),
|
|
480
|
+
_ts_metadata("design:paramtypes", [
|
|
481
|
+
Array,
|
|
482
|
+
Object
|
|
483
|
+
]),
|
|
484
|
+
_ts_metadata("design:returntype", Promise)
|
|
485
|
+
], ApiService.prototype, "updateMany", null);
|
|
486
|
+
_ts_decorate([
|
|
487
|
+
LogAction({
|
|
488
|
+
action: 'delete'
|
|
489
|
+
}),
|
|
490
|
+
_ts_metadata("design:type", Function),
|
|
491
|
+
_ts_metadata("design:paramtypes", [
|
|
492
|
+
typeof DeleteDto === "undefined" ? Object : DeleteDto,
|
|
493
|
+
Object
|
|
494
|
+
]),
|
|
495
|
+
_ts_metadata("design:returntype", Promise)
|
|
496
|
+
], ApiService.prototype, "delete", null);
|
|
@@ -11,39 +11,17 @@ function _define_property(obj, key, value) {
|
|
|
11
11
|
}
|
|
12
12
|
return obj;
|
|
13
13
|
}
|
|
14
|
-
import { instance as winstonLogger } from './winston.logger.class';
|
|
14
|
+
import { instance as winstonLogger, createModuleLogger } from './winston.logger.class';
|
|
15
15
|
import { getRequestId, getUserId, getTenantId, getCompanyId } from '../middlewares/logger.middleware';
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const tenantId = getTenantId();
|
|
24
|
-
const companyId = getCompanyId();
|
|
25
|
-
if (requestId) meta.requestId = requestId;
|
|
26
|
-
if (userId) meta.userId = userId;
|
|
27
|
-
if (tenantId) meta.tenantId = tenantId;
|
|
28
|
-
if (companyId) meta.companyId = companyId;
|
|
29
|
-
return meta;
|
|
16
|
+
function getCorrelationMeta() {
|
|
17
|
+
return Object.fromEntries(Object.entries({
|
|
18
|
+
requestId: getRequestId(),
|
|
19
|
+
userId: getUserId(),
|
|
20
|
+
tenantId: getTenantId(),
|
|
21
|
+
companyId: getCompanyId()
|
|
22
|
+
}).filter(([, v])=>v != null));
|
|
30
23
|
}
|
|
31
|
-
|
|
32
|
-
* Winston Logger Adapter
|
|
33
|
-
* Adapts Winston logger to ILogger interface for dependency injection
|
|
34
|
-
*
|
|
35
|
-
* Features:
|
|
36
|
-
* - Automatic correlation ID injection
|
|
37
|
-
* - User ID tracking
|
|
38
|
-
* - Structured metadata logging
|
|
39
|
-
*
|
|
40
|
-
* Usage:
|
|
41
|
-
* ```typescript
|
|
42
|
-
* const logger = new WinstonLoggerAdapter('MyService');
|
|
43
|
-
* logger.log('Operation completed', undefined, { orderId: '123' });
|
|
44
|
-
* // Output: { requestId: 'uuid', userId: 'user-id', context: 'MyService', message: 'Operation completed', orderId: '123' }
|
|
45
|
-
* ```
|
|
46
|
-
*/ export class WinstonLoggerAdapter {
|
|
24
|
+
export class WinstonLoggerAdapter {
|
|
47
25
|
buildLogMeta(context, args, extra) {
|
|
48
26
|
const meta = args?.length && typeof args[0] === 'object' ? args[0] : {};
|
|
49
27
|
return {
|
|
@@ -54,34 +32,30 @@ import { getRequestId, getUserId, getTenantId, getCompanyId } from '../middlewar
|
|
|
54
32
|
};
|
|
55
33
|
}
|
|
56
34
|
log(message, context, ...args) {
|
|
57
|
-
|
|
35
|
+
this.logger.info(message, this.buildLogMeta(context, args));
|
|
58
36
|
}
|
|
59
37
|
error(message, trace, context, ...args) {
|
|
60
|
-
|
|
38
|
+
this.logger.error(message, this.buildLogMeta(context, args, {
|
|
61
39
|
stack: trace
|
|
62
40
|
}));
|
|
63
41
|
}
|
|
64
42
|
warn(message, context, ...args) {
|
|
65
|
-
|
|
43
|
+
this.logger.warn(message, this.buildLogMeta(context, args));
|
|
66
44
|
}
|
|
67
45
|
debug(message, context, ...args) {
|
|
68
|
-
|
|
46
|
+
this.logger.debug(message, this.buildLogMeta(context, args));
|
|
69
47
|
}
|
|
70
48
|
verbose(message, context, ...args) {
|
|
71
|
-
|
|
49
|
+
this.logger.verbose(message, this.buildLogMeta(context, args));
|
|
72
50
|
}
|
|
73
|
-
constructor(context){
|
|
51
|
+
constructor(context, moduleName){
|
|
74
52
|
_define_property(this, "context", void 0);
|
|
53
|
+
_define_property(this, "logger", void 0);
|
|
75
54
|
this.context = context;
|
|
55
|
+
this.logger = moduleName ? createModuleLogger(moduleName) : winstonLogger;
|
|
76
56
|
}
|
|
77
57
|
}
|
|
78
|
-
|
|
79
|
-
* NestJS Logger Adapter
|
|
80
|
-
* Adapts NestJS Logger to ILogger interface
|
|
81
|
-
*
|
|
82
|
-
* Use this when you need to use NestJS's built-in logger
|
|
83
|
-
* instead of Winston (e.g., for testing)
|
|
84
|
-
*/ export class NestLoggerAdapter {
|
|
58
|
+
export class NestLoggerAdapter {
|
|
85
59
|
formatMessage(message, args) {
|
|
86
60
|
return args?.length ? `${message} ${JSON.stringify(args)}` : message;
|
|
87
61
|
}
|