@flusys/nestjs-shared 1.1.0-beta → 1.2.0-rc.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/README.md +146 -1330
- package/cjs/classes/api-controller.class.js +325 -49
- package/cjs/classes/api-service.class.js +271 -149
- package/cjs/classes/handle-custome-db.js +37 -0
- package/cjs/classes/index.js +2 -2
- package/cjs/classes/winston.logger.class.js +103 -70
- package/cjs/constants/index.js +15 -4
- package/cjs/constants/message-keys.js +68 -0
- package/cjs/constants/permissions.js +287 -0
- package/cjs/decorators/api-response.decorator.js +2 -3
- package/cjs/decorators/index.js +1 -0
- package/cjs/decorators/log-action.decorator.js +149 -0
- package/cjs/decorators/require-permission.decorator.js +5 -5
- package/cjs/dtos/delete.dto.js +10 -0
- package/cjs/dtos/filter-and-pagination.dto.js +24 -34
- package/cjs/dtos/get-by-ids.dto.js +65 -0
- package/cjs/dtos/identity-response.dto.js +4 -8
- package/cjs/dtos/index.js +1 -0
- package/cjs/dtos/pagination.dto.js +4 -8
- package/cjs/dtos/response-payload.dto.js +68 -112
- package/cjs/entities/identity.js +12 -6
- package/cjs/entities/index.js +1 -0
- package/cjs/entities/raw-type.js +4 -0
- package/cjs/entities/user-root.js +15 -15
- 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 +151 -0
- package/cjs/exceptions/index.js +1 -0
- package/cjs/exceptions/permission.exception.js +13 -9
- package/cjs/filters/global-exception.filter.js +279 -0
- package/cjs/filters/index.js +18 -0
- package/cjs/guards/jwt-auth.guard.js +4 -1
- package/cjs/guards/permission.guard.js +88 -148
- package/cjs/index.js +2 -0
- package/cjs/interceptors/idempotency.interceptor.js +1 -1
- package/cjs/interceptors/index.js +1 -4
- package/cjs/interceptors/set-user-field-on-body.interceptor.js +60 -0
- package/cjs/interceptors/slug.interceptor.js +30 -9
- package/cjs/interfaces/datasource.interface.js +4 -0
- package/cjs/interfaces/event-manager-adapter.interface.js +11 -0
- package/cjs/interfaces/index.js +4 -2
- package/cjs/interfaces/module-config.interface.js +4 -0
- package/cjs/interfaces/notification-adapter.interface.js +11 -0
- package/cjs/interfaces/permission.interface.js +1 -1
- package/cjs/middlewares/logger.middleware.js +133 -115
- package/cjs/modules/cache/cache.module.js +3 -3
- package/cjs/modules/datasource/index.js +0 -1
- package/cjs/modules/datasource/multi-tenant-datasource.service.js +60 -183
- package/cjs/modules/utils/utils.service.js +27 -206
- package/cjs/utils/date-time.util.js +94 -0
- package/cjs/utils/html-sanitizer.util.js +64 -0
- package/cjs/utils/index.js +5 -1
- package/cjs/utils/query-helpers.util.js +60 -0
- package/cjs/utils/request.util.js +96 -0
- package/cjs/utils/string.util.js +63 -0
- package/classes/api-controller.class.d.ts +16 -8
- package/classes/api-service.class.d.ts +30 -25
- package/classes/handle-custome-db.d.ts +3 -0
- package/classes/index.d.ts +2 -2
- package/classes/winston.logger.class.d.ts +1 -0
- package/constants/index.d.ts +2 -1
- package/constants/message-keys.d.ts +45 -0
- package/constants/permissions.d.ts +306 -0
- package/decorators/api-response.decorator.d.ts +1 -1
- package/decorators/current-user.decorator.d.ts +1 -1
- package/decorators/index.d.ts +1 -0
- package/decorators/log-action.decorator.d.ts +8 -0
- package/decorators/require-permission.decorator.d.ts +2 -2
- package/dtos/delete.dto.d.ts +1 -0
- package/dtos/filter-and-pagination.dto.d.ts +0 -2
- package/dtos/get-by-ids.dto.d.ts +4 -0
- package/dtos/index.d.ts +1 -0
- package/dtos/response-payload.dto.d.ts +8 -20
- package/entities/index.d.ts +1 -0
- package/entities/raw-type.d.ts +1 -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 +2 -2
- package/fesm/classes/api-controller.class.js +326 -50
- package/fesm/classes/api-service.class.js +274 -152
- package/fesm/classes/handle-custome-db.js +19 -0
- package/fesm/classes/index.js +3 -2
- package/fesm/classes/winston.logger.class.js +100 -68
- package/fesm/constants/index.js +4 -1
- package/fesm/constants/message-keys.js +49 -0
- package/fesm/constants/permissions.js +200 -0
- package/fesm/decorators/api-response.decorator.js +3 -21
- package/fesm/decorators/index.js +1 -0
- package/fesm/decorators/log-action.decorator.js +139 -0
- package/fesm/decorators/require-permission.decorator.js +17 -65
- package/fesm/dtos/delete.dto.js +12 -2
- package/fesm/dtos/filter-and-pagination.dto.js +26 -47
- package/fesm/dtos/get-by-ids.dto.js +55 -0
- package/fesm/dtos/identity-response.dto.js +4 -8
- package/fesm/dtos/index.js +1 -0
- package/fesm/dtos/pagination.dto.js +4 -8
- package/fesm/dtos/response-payload.dto.js +68 -103
- package/fesm/entities/identity.js +12 -6
- package/fesm/entities/index.js +1 -0
- package/fesm/entities/raw-type.js +1 -0
- package/fesm/entities/user-root.js +15 -15
- 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 +115 -0
- package/fesm/exceptions/index.js +1 -0
- package/fesm/exceptions/permission.exception.js +16 -18
- package/fesm/filters/global-exception.filter.js +269 -0
- package/fesm/filters/index.js +1 -0
- package/fesm/guards/jwt-auth.guard.js +5 -2
- package/fesm/guards/permission.guard.js +90 -150
- package/fesm/index.js +2 -0
- package/fesm/interceptors/idempotency.interceptor.js +2 -2
- package/fesm/interceptors/index.js +1 -4
- package/fesm/interceptors/set-user-field-on-body.interceptor.js +39 -0
- package/fesm/interceptors/slug.interceptor.js +31 -10
- package/fesm/interfaces/datasource.interface.js +1 -0
- package/fesm/interfaces/event-manager-adapter.interface.js +1 -0
- package/fesm/interfaces/index.js +4 -2
- package/fesm/interfaces/module-config.interface.js +5 -0
- package/fesm/interfaces/notification-adapter.interface.js +1 -0
- package/fesm/interfaces/permission.interface.js +1 -3
- package/fesm/middlewares/logger.middleware.js +133 -109
- package/fesm/modules/cache/cache.module.js +2 -2
- package/fesm/modules/datasource/index.js +0 -1
- package/fesm/modules/datasource/multi-tenant-datasource.service.js +61 -184
- package/fesm/modules/utils/utils.service.js +27 -206
- package/fesm/utils/date-time.util.js +70 -0
- package/fesm/utils/html-sanitizer.util.js +69 -0
- package/fesm/utils/index.js +5 -1
- package/fesm/utils/query-helpers.util.js +85 -0
- package/fesm/utils/request.util.js +81 -0
- package/fesm/utils/string.util.js +71 -0
- package/filters/global-exception.filter.d.ts +9 -0
- package/filters/index.d.ts +1 -0
- package/guards/permission.guard.d.ts +4 -6
- package/index.d.ts +2 -0
- package/interceptors/idempotency.interceptor.d.ts +1 -1
- package/interceptors/index.d.ts +1 -4
- package/interceptors/set-user-field-on-body.interceptor.d.ts +5 -0
- package/interceptors/slug.interceptor.d.ts +2 -1
- package/interfaces/api.interface.d.ts +4 -2
- package/interfaces/datasource.interface.d.ts +5 -0
- package/interfaces/event-manager-adapter.interface.d.ts +43 -0
- package/interfaces/identity.interface.d.ts +4 -4
- package/interfaces/index.d.ts +4 -2
- package/interfaces/logged-user-info.interface.d.ts +0 -2
- package/interfaces/module-config.interface.d.ts +6 -0
- package/interfaces/notification-adapter.interface.d.ts +21 -0
- package/interfaces/permission.interface.d.ts +13 -9
- package/middlewares/logger.middleware.d.ts +2 -2
- package/modules/datasource/index.d.ts +0 -1
- package/modules/datasource/multi-tenant-datasource.service.d.ts +5 -16
- package/modules/utils/utils.service.d.ts +3 -14
- package/package.json +21 -14
- package/utils/date-time.util.d.ts +8 -0
- package/utils/html-sanitizer.util.d.ts +2 -0
- package/utils/index.d.ts +5 -1
- package/utils/query-helpers.util.d.ts +16 -0
- package/utils/request.util.d.ts +6 -0
- package/utils/string.util.d.ts +2 -0
- package/cjs/classes/request-scoped-api.service.js +0 -61
- package/cjs/classes/winston-logger-adapter.class.js +0 -121
- package/cjs/interceptors/query-performance.interceptor.js +0 -66
- package/cjs/interceptors/set-create-by-on-body.interceptor.js +0 -40
- package/cjs/interceptors/set-delete-by-on-body.interceptor.js +0 -40
- package/cjs/interceptors/set-update-by-on-body.interceptor.js +0 -40
- package/cjs/interfaces/base-query.interface.js +0 -6
- package/cjs/interfaces/logger.interface.js +0 -7
- package/cjs/modules/datasource/datasource.module.js +0 -120
- package/cjs/utils/error-handler.util.js +0 -67
- package/classes/request-scoped-api.service.d.ts +0 -13
- package/classes/winston-logger-adapter.class.d.ts +0 -20
- package/fesm/classes/request-scoped-api.service.js +0 -51
- package/fesm/classes/winston-logger-adapter.class.js +0 -124
- package/fesm/interceptors/query-performance.interceptor.js +0 -56
- package/fesm/interceptors/set-create-by-on-body.interceptor.js +0 -30
- package/fesm/interceptors/set-delete-by-on-body.interceptor.js +0 -30
- package/fesm/interceptors/set-update-by-on-body.interceptor.js +0 -30
- package/fesm/interfaces/base-query.interface.js +0 -3
- package/fesm/interfaces/logger.interface.js +0 -4
- package/fesm/modules/datasource/datasource.module.js +0 -110
- package/fesm/utils/error-handler.util.js +0 -59
- package/interceptors/query-performance.interceptor.d.ts +0 -8
- package/interceptors/set-create-by-on-body.interceptor.d.ts +0 -5
- package/interceptors/set-delete-by-on-body.interceptor.d.ts +0 -5
- package/interceptors/set-update-by-on-body.interceptor.d.ts +0 -5
- package/interfaces/base-query.interface.d.ts +0 -7
- package/interfaces/logger.interface.d.ts +0 -7
- package/modules/datasource/datasource.module.d.ts +0 -18
- package/utils/error-handler.util.d.ts +0 -24
|
@@ -11,130 +11,129 @@ function _define_property(obj, key, value) {
|
|
|
11
11
|
}
|
|
12
12
|
return obj;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 { Injectable, InternalServerErrorException, NotFoundException, Scope } from '@nestjs/common';
|
|
24
|
+
import { EntityTarget, In } from 'typeorm';
|
|
25
|
+
import { ERROR_MESSAGES, SYSTEM_MESSAGES } from '../constants';
|
|
26
|
+
import { LogAction } from '../decorators/log-action.decorator';
|
|
27
|
+
import { DeleteDto } from '../dtos';
|
|
28
|
+
import { IDataSourceProvider } from '../interfaces';
|
|
29
|
+
import { UtilsService } from '../modules/utils/utils.service';
|
|
30
|
+
import { HybridCache } from './hybrid-cache.class';
|
|
31
|
+
export class ApiService {
|
|
32
|
+
resolveEntity() {
|
|
33
|
+
return this._entity;
|
|
34
|
+
}
|
|
35
|
+
getDataSourceProvider() {
|
|
36
|
+
return this._dataSourceProvider;
|
|
37
|
+
}
|
|
38
|
+
async ensureDataSourceRepository() {
|
|
39
|
+
if (!this.repositoryInitialized) {
|
|
40
|
+
const entity = this.resolveEntity();
|
|
41
|
+
const provider = this.getDataSourceProvider();
|
|
42
|
+
this.repository = await provider.getRepository(entity);
|
|
43
|
+
this.repositoryInitialized = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async resolveRepositories(entities) {
|
|
47
|
+
const provider = this.getDataSourceProvider();
|
|
48
|
+
const repositories = [];
|
|
49
|
+
for (const entity of entities){
|
|
50
|
+
repositories.push(await provider.getRepository(entity));
|
|
51
|
+
}
|
|
52
|
+
return repositories;
|
|
53
|
+
}
|
|
54
|
+
async getDataSourceForService() {
|
|
55
|
+
return this.getDataSourceProvider().getDataSource();
|
|
56
|
+
}
|
|
18
57
|
async insert(dto, user) {
|
|
19
|
-
|
|
20
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
21
|
-
await qr.connect();
|
|
22
|
-
await qr.startTransaction();
|
|
23
|
-
try {
|
|
58
|
+
return this.executeInTransaction('insert', async (qr)=>{
|
|
24
59
|
await this.beforeInsertOperation(dto, user, qr);
|
|
25
60
|
const entities = await this.convertRequestDtoToEntity(dto, user);
|
|
26
61
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
27
|
-
await this.afterInsertOperation(saved, user, qr);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
])
|
|
34
|
-
]);
|
|
35
|
-
const first = Array.isArray(saved) ? saved[0] : saved;
|
|
36
|
-
return this.convertEntityToResponseDto(first, false);
|
|
37
|
-
} catch (error) {
|
|
38
|
-
await qr.rollbackTransaction();
|
|
39
|
-
this.handleError(error, 'insert');
|
|
40
|
-
} finally{
|
|
41
|
-
await qr.release();
|
|
42
|
-
}
|
|
62
|
+
await this.afterInsertOperation(this.ensureArray(saved), dto, user, qr);
|
|
63
|
+
return {
|
|
64
|
+
saved,
|
|
65
|
+
returnFirst: true
|
|
66
|
+
};
|
|
67
|
+
});
|
|
43
68
|
}
|
|
44
69
|
async insertMany(dtos, user) {
|
|
45
|
-
|
|
46
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
47
|
-
await qr.connect();
|
|
48
|
-
await qr.startTransaction();
|
|
49
|
-
try {
|
|
70
|
+
return this.executeInTransaction('insertMany', async (qr)=>{
|
|
50
71
|
await this.beforeInsertOperation(dtos, user, qr);
|
|
51
72
|
const entities = await this.convertRequestDtoToEntity(dtos, user);
|
|
52
73
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
53
|
-
await this.afterInsertOperation(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.clearCacheForId(Array.isArray(saved) ? saved : [
|
|
60
|
-
saved
|
|
61
|
-
])
|
|
62
|
-
]);
|
|
63
|
-
const list = (Array.isArray(saved) ? saved : [
|
|
64
|
-
saved
|
|
65
|
-
]).map((e)=>this.convertEntityToResponseDto(e, false));
|
|
66
|
-
return list;
|
|
67
|
-
} catch (error) {
|
|
68
|
-
await qr.rollbackTransaction();
|
|
69
|
-
this.handleError(error, 'insertMany');
|
|
70
|
-
} finally{
|
|
71
|
-
await qr.release();
|
|
72
|
-
}
|
|
74
|
+
await this.afterInsertOperation(this.ensureArray(saved), dtos, user, qr);
|
|
75
|
+
return {
|
|
76
|
+
saved,
|
|
77
|
+
returnFirst: false
|
|
78
|
+
};
|
|
79
|
+
});
|
|
73
80
|
}
|
|
74
81
|
async update(dto, user) {
|
|
75
|
-
|
|
76
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
77
|
-
await qr.connect();
|
|
78
|
-
await qr.startTransaction();
|
|
79
|
-
try {
|
|
82
|
+
return this.executeInTransaction('update', async (qr)=>{
|
|
80
83
|
await this.beforeUpdateOperation(dto, user, qr);
|
|
81
84
|
const entities = await this.convertRequestDtoToEntity(dto, user);
|
|
82
85
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
83
|
-
await this.afterUpdateOperation(saved, user, qr);
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
])
|
|
90
|
-
]);
|
|
91
|
-
const first = Array.isArray(saved) ? saved[0] : saved;
|
|
92
|
-
return this.convertEntityToResponseDto(first, false);
|
|
93
|
-
} catch (error) {
|
|
94
|
-
await qr.rollbackTransaction();
|
|
95
|
-
this.handleError(error, 'update');
|
|
96
|
-
} finally{
|
|
97
|
-
await qr.release();
|
|
98
|
-
}
|
|
86
|
+
await this.afterUpdateOperation(this.ensureArray(saved), dto, user, qr);
|
|
87
|
+
return {
|
|
88
|
+
saved,
|
|
89
|
+
returnFirst: true
|
|
90
|
+
};
|
|
91
|
+
});
|
|
99
92
|
}
|
|
100
93
|
async updateMany(dtos, user) {
|
|
101
|
-
|
|
102
|
-
const qr = this.repository.manager.connection.createQueryRunner();
|
|
103
|
-
await qr.connect();
|
|
104
|
-
await qr.startTransaction();
|
|
105
|
-
try {
|
|
94
|
+
return this.executeInTransaction('updateMany', async (qr)=>{
|
|
106
95
|
await this.beforeUpdateOperation(dtos, user, qr);
|
|
107
96
|
const entities = await this.convertRequestDtoToEntity(dtos, user);
|
|
108
97
|
const saved = await qr.manager.save(this.repository.target, entities);
|
|
109
|
-
await this.afterUpdateOperation(
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
]
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
98
|
+
await this.afterUpdateOperation(this.ensureArray(saved), dtos, user, qr);
|
|
99
|
+
return {
|
|
100
|
+
saved,
|
|
101
|
+
returnFirst: false
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
async bulkUpsert(toInsert, toUpdate, user) {
|
|
106
|
+
return this.executeInTransaction('bulkUpsert', async (qr)=>{
|
|
107
|
+
const allResults = [];
|
|
108
|
+
if (toInsert.length > 0) {
|
|
109
|
+
await this.beforeInsertOperation(toInsert, user, qr);
|
|
110
|
+
const insertedEntities = await this.convertRequestDtoToEntity(toInsert, user);
|
|
111
|
+
const insertedSaved = await qr.manager.save(this.repository.target, insertedEntities);
|
|
112
|
+
await this.afterInsertOperation(this.ensureArray(insertedSaved), toInsert, user, qr);
|
|
113
|
+
allResults.push(...this.ensureArray(insertedSaved));
|
|
114
|
+
}
|
|
115
|
+
if (toUpdate.length > 0) {
|
|
116
|
+
await this.beforeUpdateOperation(toUpdate, user, qr);
|
|
117
|
+
const updatedEntities = await this.convertRequestDtoToEntity(toUpdate, user);
|
|
118
|
+
const updatedSaved = await qr.manager.save(this.repository.target, updatedEntities);
|
|
119
|
+
await this.afterUpdateOperation(this.ensureArray(updatedSaved), toUpdate, user, qr);
|
|
120
|
+
allResults.push(...this.ensureArray(updatedSaved));
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
saved: allResults,
|
|
124
|
+
returnFirst: false
|
|
125
|
+
};
|
|
126
|
+
});
|
|
129
127
|
}
|
|
130
|
-
async findByIds(ids, user) {
|
|
131
|
-
await this.
|
|
128
|
+
async findByIds(ids, user, select) {
|
|
129
|
+
await this.ensureDataSourceRepository();
|
|
132
130
|
try {
|
|
133
131
|
const query = this.repository.createQueryBuilder(this.entityName);
|
|
134
132
|
query.where({
|
|
135
133
|
id: In(ids)
|
|
136
134
|
});
|
|
137
|
-
const
|
|
135
|
+
const selectArray = typeof select === 'string' ? select.split(',').map((s)=>s.trim()) : select;
|
|
136
|
+
const { query: finalQuery, isRaw } = await this.getSelectQuery(query, user, selectArray);
|
|
138
137
|
let output;
|
|
139
138
|
if (isRaw) {
|
|
140
139
|
output = await finalQuery.getRawMany();
|
|
@@ -142,7 +141,10 @@ import { In } from 'typeorm';
|
|
|
142
141
|
output = await finalQuery.getMany();
|
|
143
142
|
}
|
|
144
143
|
const result = this.convertEntityListToResponseListDto(output, isRaw);
|
|
145
|
-
if (!result || !result.length) throw new NotFoundException(
|
|
144
|
+
if (!result || !result.length) throw new NotFoundException({
|
|
145
|
+
message: 'No Data Found',
|
|
146
|
+
messageKey: ERROR_MESSAGES.NOT_FOUND
|
|
147
|
+
});
|
|
146
148
|
return result;
|
|
147
149
|
} catch (error) {
|
|
148
150
|
if (error instanceof NotFoundException) {
|
|
@@ -152,7 +154,7 @@ import { In } from 'typeorm';
|
|
|
152
154
|
}
|
|
153
155
|
}
|
|
154
156
|
async findById(id, user, select) {
|
|
155
|
-
await this.
|
|
157
|
+
await this.ensureDataSourceRepository();
|
|
156
158
|
try {
|
|
157
159
|
const query = this.repository.createQueryBuilder(this.entityName);
|
|
158
160
|
query.where({
|
|
@@ -166,15 +168,17 @@ import { In } from 'typeorm';
|
|
|
166
168
|
result = await this.cacheManager.get(cacheKey);
|
|
167
169
|
}
|
|
168
170
|
if (!result) {
|
|
169
|
-
let output;
|
|
170
171
|
if (isRaw) {
|
|
171
|
-
|
|
172
|
-
const convertResult = this.convertEntityListToResponseListDto(
|
|
172
|
+
const rawOutput = await finalQuery.getRawMany();
|
|
173
|
+
const convertResult = this.convertEntityListToResponseListDto(rawOutput, isRaw);
|
|
173
174
|
if (convertResult.length) result = convertResult[0];
|
|
174
175
|
} else {
|
|
175
|
-
|
|
176
|
-
if (!
|
|
177
|
-
|
|
176
|
+
const singleOutput = await finalQuery.getOne();
|
|
177
|
+
if (!singleOutput) throw new NotFoundException({
|
|
178
|
+
message: 'No Data Found',
|
|
179
|
+
messageKey: ERROR_MESSAGES.NOT_FOUND
|
|
180
|
+
});
|
|
181
|
+
result = this.convertEntityToResponseDto(singleOutput, false);
|
|
178
182
|
}
|
|
179
183
|
if (this.isCacheable) {
|
|
180
184
|
await this.cacheManager.set(cacheKey, result);
|
|
@@ -190,43 +194,34 @@ import { In } from 'typeorm';
|
|
|
190
194
|
}
|
|
191
195
|
}
|
|
192
196
|
async getAll(search, filterAndPaginationDto, user) {
|
|
193
|
-
await this.
|
|
197
|
+
await this.ensureDataSourceRepository();
|
|
194
198
|
try {
|
|
195
199
|
let data;
|
|
196
200
|
let total;
|
|
197
201
|
let isRaw = false;
|
|
198
202
|
let query = this.repository.createQueryBuilder(this.entityName);
|
|
199
|
-
// Apply filters
|
|
200
203
|
if (filterAndPaginationDto.filter) {
|
|
201
204
|
const { query: filterQuery, isRaw: filterIsRaw } = await this.getFilterQuery(query, filterAndPaginationDto.filter, user);
|
|
202
205
|
query = filterQuery;
|
|
203
206
|
isRaw = isRaw || filterIsRaw;
|
|
204
207
|
}
|
|
205
|
-
// Apply search
|
|
206
208
|
if (search) {
|
|
207
209
|
const { query: searchQuery, isRaw: searchIsRaw } = await this.getGlobalSearchQuery(query, search, user);
|
|
208
210
|
query = searchQuery;
|
|
209
211
|
isRaw = isRaw || searchIsRaw;
|
|
210
212
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
query = selectQuery;
|
|
215
|
-
isRaw = isRaw || selectIsRaw;
|
|
216
|
-
}
|
|
217
|
-
// Apply sort
|
|
213
|
+
const { query: selectQuery, isRaw: selectIsRaw } = await this.getSelectQuery(query, user, filterAndPaginationDto.select);
|
|
214
|
+
query = selectQuery;
|
|
215
|
+
isRaw = isRaw || selectIsRaw;
|
|
218
216
|
if (filterAndPaginationDto.sort) {
|
|
219
217
|
const { query: sortQuery, isRaw: sortIsRaw } = await this.getSortQuery(query, filterAndPaginationDto.sort, user);
|
|
220
218
|
query = sortQuery;
|
|
221
219
|
isRaw = isRaw || sortIsRaw;
|
|
222
220
|
}
|
|
223
|
-
// Include soft-deleted if requested
|
|
224
221
|
if (filterAndPaginationDto.withDeleted) query.withDeleted();
|
|
225
|
-
// Extra manipulation
|
|
226
222
|
const { query: extraQuery, isRaw: extraIsRaw } = await this.getExtraManipulateQuery(query, filterAndPaginationDto, user);
|
|
227
223
|
query = extraQuery;
|
|
228
224
|
isRaw = isRaw || extraIsRaw;
|
|
229
|
-
// Pagination
|
|
230
225
|
if (filterAndPaginationDto.pagination) {
|
|
231
226
|
const offset = filterAndPaginationDto.pagination.currentPage * filterAndPaginationDto.pagination.pageSize;
|
|
232
227
|
const limit = filterAndPaginationDto.pagination.pageSize;
|
|
@@ -236,7 +231,6 @@ import { In } from 'typeorm';
|
|
|
236
231
|
query.skip(offset).take(limit);
|
|
237
232
|
}
|
|
238
233
|
}
|
|
239
|
-
// Generate cache key
|
|
240
234
|
let cacheKey = '';
|
|
241
235
|
if (this.isCacheable) {
|
|
242
236
|
cacheKey = this.utilsService.getCacheKey(this.entityName, {
|
|
@@ -250,8 +244,9 @@ import { In } from 'typeorm';
|
|
|
250
244
|
}
|
|
251
245
|
}
|
|
252
246
|
if (isRaw) {
|
|
253
|
-
|
|
254
|
-
|
|
247
|
+
const rawSubQuery = query.clone().offset(undefined).limit(undefined);
|
|
248
|
+
rawSubQuery.expressionMap.orderBys = {};
|
|
249
|
+
rawSubQuery.distinct(true);
|
|
255
250
|
const countSql = `
|
|
256
251
|
SELECT COUNT(*) as count
|
|
257
252
|
FROM (
|
|
@@ -262,10 +257,20 @@ import { In } from 'typeorm';
|
|
|
262
257
|
`;
|
|
263
258
|
const parameters = rawSubQuery.getParameters();
|
|
264
259
|
const orderedValues = [];
|
|
260
|
+
const isPostgres = this.repository.manager.connection.options.type === 'postgres';
|
|
261
|
+
let paramIndex = 0;
|
|
265
262
|
const convertedQuery = countSql.replace(/:(\w+)/g, (_, key)=>{
|
|
266
|
-
if (!(key in parameters))
|
|
263
|
+
if (!(key in parameters)) {
|
|
264
|
+
throw new InternalServerErrorException({
|
|
265
|
+
message: `Missing parameter value for: ${key}`,
|
|
266
|
+
messageKey: SYSTEM_MESSAGES.MISSING_PARAMETER,
|
|
267
|
+
messageVariables: {
|
|
268
|
+
key
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
}
|
|
267
272
|
orderedValues.push(parameters[key]);
|
|
268
|
-
return '?';
|
|
273
|
+
return isPostgres ? `$${++paramIndex}` : '?';
|
|
269
274
|
});
|
|
270
275
|
const result = await this.repository.query(convertedQuery, orderedValues);
|
|
271
276
|
total = Number(result[0]?.count || 0);
|
|
@@ -288,7 +293,7 @@ import { In } from 'typeorm';
|
|
|
288
293
|
}
|
|
289
294
|
}
|
|
290
295
|
async delete(option, user) {
|
|
291
|
-
await this.
|
|
296
|
+
await this.ensureDataSourceRepository();
|
|
292
297
|
const queryRunner = this.repository.manager.connection.createQueryRunner();
|
|
293
298
|
await queryRunner.connect();
|
|
294
299
|
await queryRunner.startTransaction();
|
|
@@ -314,13 +319,12 @@ import { In } from 'typeorm';
|
|
|
314
319
|
id
|
|
315
320
|
};
|
|
316
321
|
});
|
|
317
|
-
await this.afterDeleteOperation(ids, user, queryRunner);
|
|
322
|
+
await this.afterDeleteOperation(ids, option, user, queryRunner);
|
|
318
323
|
await queryRunner.commitTransaction();
|
|
319
324
|
await Promise.all([
|
|
320
325
|
this.clearCacheForAll(),
|
|
321
326
|
this.clearCacheForId(ids)
|
|
322
327
|
]);
|
|
323
|
-
// return null per IService contract
|
|
324
328
|
return null;
|
|
325
329
|
} catch (error) {
|
|
326
330
|
await queryRunner.rollbackTransaction();
|
|
@@ -329,29 +333,58 @@ import { In } from 'typeorm';
|
|
|
329
333
|
await queryRunner.release();
|
|
330
334
|
}
|
|
331
335
|
}
|
|
332
|
-
// Caching
|
|
333
336
|
async clearCacheForAll() {
|
|
334
337
|
await this.utilsService.clearCache(this.entityName, this.cacheManager);
|
|
335
338
|
}
|
|
336
339
|
async clearCacheForId(entities) {
|
|
337
340
|
await Promise.all(entities.map((item)=>this.utilsService.clearCache(this.entityName, this.cacheManager, item.id)));
|
|
338
341
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
342
|
+
handleError(error, _operation) {
|
|
343
|
+
if (error instanceof Error) {
|
|
344
|
+
throw error;
|
|
345
|
+
}
|
|
346
|
+
throw new InternalServerErrorException({
|
|
347
|
+
message: typeof error === 'string' ? error : 'Unknown error',
|
|
348
|
+
messageKey: ERROR_MESSAGES.INTERNAL
|
|
344
349
|
});
|
|
345
|
-
ErrorHandler.rethrowError(error);
|
|
346
350
|
}
|
|
347
|
-
|
|
348
|
-
|
|
351
|
+
ensureArray(value) {
|
|
352
|
+
return Array.isArray(value) ? value : [
|
|
353
|
+
value
|
|
354
|
+
];
|
|
355
|
+
}
|
|
356
|
+
async executeInTransaction(operation, fn) {
|
|
357
|
+
await this.ensureDataSourceRepository();
|
|
358
|
+
const qr = this.repository.manager.connection.createQueryRunner();
|
|
359
|
+
await qr.connect();
|
|
360
|
+
await qr.startTransaction();
|
|
361
|
+
try {
|
|
362
|
+
const { saved, returnFirst } = await fn(qr);
|
|
363
|
+
await qr.commitTransaction();
|
|
364
|
+
const savedArray = this.ensureArray(saved);
|
|
365
|
+
if (this.isCacheable) {
|
|
366
|
+
await Promise.all([
|
|
367
|
+
this.clearCacheForAll(),
|
|
368
|
+
this.clearCacheForId(savedArray)
|
|
369
|
+
]);
|
|
370
|
+
}
|
|
371
|
+
if (returnFirst) {
|
|
372
|
+
return this.convertEntityToResponseDto(savedArray[0], false);
|
|
373
|
+
}
|
|
374
|
+
return savedArray.map((e)=>this.convertEntityToResponseDto(e, false));
|
|
375
|
+
} catch (error) {
|
|
376
|
+
await qr.rollbackTransaction();
|
|
377
|
+
this.handleError(error, operation);
|
|
378
|
+
} finally{
|
|
379
|
+
await qr.release();
|
|
380
|
+
}
|
|
381
|
+
}
|
|
349
382
|
async beforeInsertOperation(_dto, _user, _queryRunner) {}
|
|
350
|
-
async afterInsertOperation(_entity, _user, _queryRunner) {}
|
|
383
|
+
async afterInsertOperation(_entity, _dto, _user, _queryRunner) {}
|
|
351
384
|
async beforeUpdateOperation(_dto, _user, _queryRunner) {}
|
|
352
|
-
async afterUpdateOperation(_entity, _user, _queryRunner) {}
|
|
385
|
+
async afterUpdateOperation(_entity, _dto, _user, _queryRunner) {}
|
|
353
386
|
async beforeDeleteOperation(_dto, _user, _queryRunner) {}
|
|
354
|
-
async afterDeleteOperation(_entity, _user, _queryRunner) {}
|
|
387
|
+
async afterDeleteOperation(_entity, _dto, _user, _queryRunner) {}
|
|
355
388
|
async getFilterQuery(query, filter, _user) {
|
|
356
389
|
Object.entries(filter).forEach(([key, value])=>{
|
|
357
390
|
query.andWhere(`${this.entityName}.${key} = :value`, {
|
|
@@ -394,7 +427,6 @@ import { In } from 'typeorm';
|
|
|
394
427
|
isRaw: false
|
|
395
428
|
};
|
|
396
429
|
}
|
|
397
|
-
// DTO conversion
|
|
398
430
|
async convertRequestDtoToEntity(dto, user) {
|
|
399
431
|
return Array.isArray(dto) ? await this.convertArrayDtoToEntities(dto, user) : [
|
|
400
432
|
await this.convertSingleDtoToEntity(dto, user)
|
|
@@ -408,7 +440,10 @@ import { In } from 'typeorm';
|
|
|
408
440
|
id: d.id
|
|
409
441
|
}
|
|
410
442
|
});
|
|
411
|
-
if (!existing) throw new NotFoundException(
|
|
443
|
+
if (!existing) throw new NotFoundException({
|
|
444
|
+
message: 'No such entity data found for update! Please, Try Again.',
|
|
445
|
+
messageKey: ERROR_MESSAGES.NOT_FOUND
|
|
446
|
+
});
|
|
412
447
|
return Object.assign(existing, d);
|
|
413
448
|
}
|
|
414
449
|
delete d.id;
|
|
@@ -421,26 +456,113 @@ import { In } from 'typeorm';
|
|
|
421
456
|
return Object.assign({}, entity);
|
|
422
457
|
}
|
|
423
458
|
convertEntityListToResponseListDto(entities, _isRaw) {
|
|
424
|
-
return entities.map((entity)=>
|
|
459
|
+
return entities.map((entity)=>this.convertEntityToResponseDto(entity, _isRaw));
|
|
425
460
|
}
|
|
426
461
|
async getEntityClass() {
|
|
427
|
-
return
|
|
462
|
+
return this.repository.create();
|
|
428
463
|
}
|
|
429
|
-
constructor(entityName,
|
|
464
|
+
constructor(entityName, cacheManager, utilsService, _loggerName, isCacheable = false, moduleName, entity, dataSourceProvider){
|
|
430
465
|
_define_property(this, "entityName", void 0);
|
|
431
|
-
_define_property(this, "repository", void 0);
|
|
432
466
|
_define_property(this, "cacheManager", void 0);
|
|
433
467
|
_define_property(this, "utilsService", void 0);
|
|
434
|
-
_define_property(this, "
|
|
468
|
+
_define_property(this, "_loggerName", void 0);
|
|
435
469
|
_define_property(this, "isCacheable", void 0);
|
|
436
|
-
_define_property(this, "
|
|
470
|
+
_define_property(this, "moduleName", void 0);
|
|
471
|
+
_define_property(this, "repository", void 0);
|
|
472
|
+
_define_property(this, "repositoryInitialized", void 0);
|
|
473
|
+
_define_property(this, "_entity", void 0);
|
|
474
|
+
_define_property(this, "_dataSourceProvider", void 0);
|
|
437
475
|
this.entityName = entityName;
|
|
438
|
-
this.repository = repository;
|
|
439
476
|
this.cacheManager = cacheManager;
|
|
440
477
|
this.utilsService = utilsService;
|
|
441
|
-
this.
|
|
478
|
+
this._loggerName = _loggerName;
|
|
442
479
|
this.isCacheable = isCacheable;
|
|
443
|
-
this.
|
|
444
|
-
this.
|
|
480
|
+
this.moduleName = moduleName;
|
|
481
|
+
this.repositoryInitialized = false;
|
|
482
|
+
this._entity = entity;
|
|
483
|
+
this._dataSourceProvider = dataSourceProvider;
|
|
445
484
|
}
|
|
446
485
|
}
|
|
486
|
+
_ts_decorate([
|
|
487
|
+
LogAction({
|
|
488
|
+
action: 'create'
|
|
489
|
+
}),
|
|
490
|
+
_ts_metadata("design:type", Function),
|
|
491
|
+
_ts_metadata("design:paramtypes", [
|
|
492
|
+
typeof CreateDtoT === "undefined" ? Object : CreateDtoT,
|
|
493
|
+
Object
|
|
494
|
+
]),
|
|
495
|
+
_ts_metadata("design:returntype", Promise)
|
|
496
|
+
], ApiService.prototype, "insert", null);
|
|
497
|
+
_ts_decorate([
|
|
498
|
+
LogAction({
|
|
499
|
+
action: 'createMany'
|
|
500
|
+
}),
|
|
501
|
+
_ts_metadata("design:type", Function),
|
|
502
|
+
_ts_metadata("design:paramtypes", [
|
|
503
|
+
typeof Array === "undefined" ? Object : Array,
|
|
504
|
+
Object
|
|
505
|
+
]),
|
|
506
|
+
_ts_metadata("design:returntype", Promise)
|
|
507
|
+
], ApiService.prototype, "insertMany", null);
|
|
508
|
+
_ts_decorate([
|
|
509
|
+
LogAction({
|
|
510
|
+
action: 'update'
|
|
511
|
+
}),
|
|
512
|
+
_ts_metadata("design:type", Function),
|
|
513
|
+
_ts_metadata("design:paramtypes", [
|
|
514
|
+
typeof UpdateDtoT === "undefined" ? Object : UpdateDtoT,
|
|
515
|
+
Object
|
|
516
|
+
]),
|
|
517
|
+
_ts_metadata("design:returntype", Promise)
|
|
518
|
+
], ApiService.prototype, "update", null);
|
|
519
|
+
_ts_decorate([
|
|
520
|
+
LogAction({
|
|
521
|
+
action: 'updateMany'
|
|
522
|
+
}),
|
|
523
|
+
_ts_metadata("design:type", Function),
|
|
524
|
+
_ts_metadata("design:paramtypes", [
|
|
525
|
+
Array,
|
|
526
|
+
Object
|
|
527
|
+
]),
|
|
528
|
+
_ts_metadata("design:returntype", Promise)
|
|
529
|
+
], ApiService.prototype, "updateMany", null);
|
|
530
|
+
_ts_decorate([
|
|
531
|
+
LogAction({
|
|
532
|
+
action: 'bulkUpsert'
|
|
533
|
+
}),
|
|
534
|
+
_ts_metadata("design:type", Function),
|
|
535
|
+
_ts_metadata("design:paramtypes", [
|
|
536
|
+
Array,
|
|
537
|
+
Array,
|
|
538
|
+
Object
|
|
539
|
+
]),
|
|
540
|
+
_ts_metadata("design:returntype", Promise)
|
|
541
|
+
], ApiService.prototype, "bulkUpsert", null);
|
|
542
|
+
_ts_decorate([
|
|
543
|
+
LogAction({
|
|
544
|
+
action: 'delete'
|
|
545
|
+
}),
|
|
546
|
+
_ts_metadata("design:type", Function),
|
|
547
|
+
_ts_metadata("design:paramtypes", [
|
|
548
|
+
typeof DeleteDto === "undefined" ? Object : DeleteDto,
|
|
549
|
+
Object
|
|
550
|
+
]),
|
|
551
|
+
_ts_metadata("design:returntype", Promise)
|
|
552
|
+
], ApiService.prototype, "delete", null);
|
|
553
|
+
ApiService = _ts_decorate([
|
|
554
|
+
Injectable({
|
|
555
|
+
scope: Scope.REQUEST
|
|
556
|
+
}),
|
|
557
|
+
_ts_metadata("design:type", Function),
|
|
558
|
+
_ts_metadata("design:paramtypes", [
|
|
559
|
+
String,
|
|
560
|
+
typeof HybridCache === "undefined" ? Object : HybridCache,
|
|
561
|
+
typeof UtilsService === "undefined" ? Object : UtilsService,
|
|
562
|
+
String,
|
|
563
|
+
Boolean,
|
|
564
|
+
String,
|
|
565
|
+
typeof EntityTarget === "undefined" ? Object : EntityTarget,
|
|
566
|
+
typeof IDataSourceProvider === "undefined" ? Object : IDataSourceProvider
|
|
567
|
+
])
|
|
568
|
+
], ApiService);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { envConfig } from '@flusys/nestjs-core';
|
|
2
|
+
export function getJsonColumnType() {
|
|
3
|
+
const driver = envConfig.getTypeOrmConfig().type;
|
|
4
|
+
if (driver === 'postgres') return 'jsonb';
|
|
5
|
+
if (driver === 'mysql') return 'json';
|
|
6
|
+
return 'simple-json';
|
|
7
|
+
}
|
|
8
|
+
export function getCastIntType() {
|
|
9
|
+
const driver = envConfig.getTypeOrmConfig().type;
|
|
10
|
+
return driver === 'postgres' ? 'INTEGER' : 'UNSIGNED';
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Converts MySQL-style `?` placeholders to PostgreSQL `$1, $2, ...` placeholders.
|
|
14
|
+
* No-op for MySQL/MariaDB.
|
|
15
|
+
*/ export function buildQuery(sql, dbType) {
|
|
16
|
+
if (dbType !== 'postgres') return sql;
|
|
17
|
+
let index = 0;
|
|
18
|
+
return sql.replace(/\?/g, ()=>`$${++index}`);
|
|
19
|
+
}
|
package/fesm/classes/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './api-controller.class';
|
|
2
2
|
export * from './api-service.class';
|
|
3
|
-
export * from './
|
|
3
|
+
export * from './handle-custome-db';
|
|
4
4
|
export * from './hybrid-cache.class';
|
|
5
|
-
export * from './winston-logger-adapter.class';
|
|
6
5
|
export * from './winston.logger.class';
|
|
6
|
+
// Re-export permission constants for convenience
|
|
7
|
+
export * from '../constants/permissions';
|