@drax/crud-back 3.4.2 → 3.5.0
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/dist/controllers/AbstractFastifyController.js +32 -7
- package/dist/repository/AbstractSqliteRepository.js +1 -1
- package/package.json +3 -3
- package/src/controllers/AbstractFastifyController.ts +76 -41
- package/src/repository/AbstractSqliteRepository.ts +1 -1
- package/test/controllers/PersonController.test.ts +148 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/types/controllers/AbstractFastifyController.d.ts +7 -2
- package/types/controllers/AbstractFastifyController.d.ts.map +1 -1
|
@@ -260,6 +260,28 @@ class AbstractFastifyController extends CommonController {
|
|
|
260
260
|
async postUpdatePartial(request, item) {
|
|
261
261
|
return item;
|
|
262
262
|
}
|
|
263
|
+
//Sobrescribir este metodo para manipular items a devolver en operaciones de lectura
|
|
264
|
+
async postRead(request, item) {
|
|
265
|
+
return item;
|
|
266
|
+
}
|
|
267
|
+
isPaginateResult(result) {
|
|
268
|
+
return typeof result === 'object' && result !== null && 'items' in result && Array.isArray(result.items);
|
|
269
|
+
}
|
|
270
|
+
async postReadItem(request, item) {
|
|
271
|
+
return this.postRead(request, item);
|
|
272
|
+
}
|
|
273
|
+
async postReadItems(request, items) {
|
|
274
|
+
if (Array.isArray(items)) {
|
|
275
|
+
return Promise.all(items.map(item => this.postRead(request, item)));
|
|
276
|
+
}
|
|
277
|
+
return items;
|
|
278
|
+
}
|
|
279
|
+
async postReadPaginate(request, pagination) {
|
|
280
|
+
if (this.isPaginateResult(pagination)) {
|
|
281
|
+
pagination.items = await Promise.all(pagination.items.map(item => this.postRead(request, item)));
|
|
282
|
+
}
|
|
283
|
+
return pagination;
|
|
284
|
+
}
|
|
263
285
|
async updatePartial(request, reply) {
|
|
264
286
|
try {
|
|
265
287
|
request.rbac.assertPermission(this.permission.Update);
|
|
@@ -355,6 +377,7 @@ class AbstractFastifyController extends CommonController {
|
|
|
355
377
|
this.assertUser(item, request.rbac);
|
|
356
378
|
}
|
|
357
379
|
this.assertTenant(item, request.rbac);
|
|
380
|
+
item = await this.postReadItem(request, item);
|
|
358
381
|
return item;
|
|
359
382
|
}
|
|
360
383
|
catch (e) {
|
|
@@ -373,6 +396,7 @@ class AbstractFastifyController extends CommonController {
|
|
|
373
396
|
if (!items || items.length === 0) {
|
|
374
397
|
throw new NotFoundError();
|
|
375
398
|
}
|
|
399
|
+
items = await this.postReadItems(request, items);
|
|
376
400
|
return items;
|
|
377
401
|
}
|
|
378
402
|
catch (e) {
|
|
@@ -393,6 +417,7 @@ class AbstractFastifyController extends CommonController {
|
|
|
393
417
|
const filters = this.parseFilters(request.query.filters);
|
|
394
418
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
395
419
|
let items = await this.service.find({ search, filters, order, orderBy, limit });
|
|
420
|
+
items = await this.postReadItems(request, items);
|
|
396
421
|
return items;
|
|
397
422
|
}
|
|
398
423
|
catch (e) {
|
|
@@ -407,6 +432,7 @@ class AbstractFastifyController extends CommonController {
|
|
|
407
432
|
const filters = this.parseFilters(request.query.filters);
|
|
408
433
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
409
434
|
let item = await this.service.findOne({ search, filters });
|
|
435
|
+
item = await this.postReadItem(request, item);
|
|
410
436
|
return item;
|
|
411
437
|
}
|
|
412
438
|
catch (e) {
|
|
@@ -426,9 +452,7 @@ class AbstractFastifyController extends CommonController {
|
|
|
426
452
|
let filters = [];
|
|
427
453
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
428
454
|
let items = await this.service.findBy(field, value, limit, filters);
|
|
429
|
-
|
|
430
|
-
// this.assertUserAndTenant(item, request.rbac)
|
|
431
|
-
// }
|
|
455
|
+
items = await this.postReadItems(request, items);
|
|
432
456
|
return items;
|
|
433
457
|
}
|
|
434
458
|
catch (e) {
|
|
@@ -447,7 +471,7 @@ class AbstractFastifyController extends CommonController {
|
|
|
447
471
|
let filters = [];
|
|
448
472
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
449
473
|
let item = await this.service.findOneBy(field, value, filters);
|
|
450
|
-
|
|
474
|
+
item = await this.postReadItem(request, item);
|
|
451
475
|
return item;
|
|
452
476
|
}
|
|
453
477
|
catch (e) {
|
|
@@ -461,8 +485,9 @@ class AbstractFastifyController extends CommonController {
|
|
|
461
485
|
const filters = [];
|
|
462
486
|
const limit = this.defaultLimit;
|
|
463
487
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
464
|
-
let
|
|
465
|
-
|
|
488
|
+
let items = await this.service.search(search, limit, filters);
|
|
489
|
+
items = await this.postReadItems(request, items);
|
|
490
|
+
return items;
|
|
466
491
|
}
|
|
467
492
|
catch (e) {
|
|
468
493
|
this.handleError(e, reply);
|
|
@@ -481,8 +506,8 @@ class AbstractFastifyController extends CommonController {
|
|
|
481
506
|
const search = request.query.search;
|
|
482
507
|
const filters = this.parseFilters(request.query.filters);
|
|
483
508
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
484
|
-
// console.log("paginate filters",filters)
|
|
485
509
|
let paginateResult = await this.service.paginate({ page, limit, orderBy, order, search, filters });
|
|
510
|
+
paginateResult = await this.postReadPaginate(request, paginateResult);
|
|
486
511
|
return paginateResult;
|
|
487
512
|
}
|
|
488
513
|
catch (e) {
|
|
@@ -220,7 +220,7 @@ class AbstractSqliteRepository {
|
|
|
220
220
|
total: rCount.count,
|
|
221
221
|
items
|
|
222
222
|
};
|
|
223
|
-
console.log('Pagination result:', JSON.stringify(pagination,
|
|
223
|
+
// console.log('Pagination result:', JSON.stringify(pagination,null,4))
|
|
224
224
|
return pagination;
|
|
225
225
|
}
|
|
226
226
|
async find({ limit = 5, orderBy = '', order = 'desc', search = '', filters = [] }) {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.
|
|
6
|
+
"version": "3.5.0",
|
|
7
7
|
"description": "Crud utils across modules",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "types/index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"@drax/common-back": "^3.0.0",
|
|
26
26
|
"@drax/common-share": "^3.0.0",
|
|
27
27
|
"@drax/identity-share": "^3.0.0",
|
|
28
|
-
"@drax/media-back": "^3.
|
|
28
|
+
"@drax/media-back": "^3.5.0",
|
|
29
29
|
"@graphql-tools/load-files": "^7.0.0",
|
|
30
30
|
"@graphql-tools/merge": "^9.0.4",
|
|
31
31
|
"mongoose": "^8.23.0",
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"typescript": "^5.9.3",
|
|
48
48
|
"vitest": "^3.2.4"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "a79ccbba44732026c3e75980a332062c2d12f35f"
|
|
51
51
|
}
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
IDraxPermission,
|
|
15
15
|
IDraxFieldFilter,
|
|
16
16
|
IDraxExportResponse,
|
|
17
|
-
IDraxCrudEvent
|
|
17
|
+
IDraxCrudEvent,
|
|
18
|
+
IDraxPaginateResult
|
|
18
19
|
} from "@drax/crud-share";
|
|
19
20
|
import {join} from "path";
|
|
20
21
|
import QueryFilterRegex from "../regexs/QueryFilterRegex.js";
|
|
@@ -98,7 +99,6 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
|
|
101
|
-
|
|
102
102
|
protected parseFilters(stringFilters: string): IDraxFieldFilter[] {
|
|
103
103
|
try {
|
|
104
104
|
if (!stringFilters) {
|
|
@@ -114,7 +114,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
114
114
|
filterArray.forEach((filter) => {
|
|
115
115
|
const [field, operator, value] = filter.split(";")
|
|
116
116
|
|
|
117
|
-
if(field && operator && (
|
|
117
|
+
if (field && operator && (operator === 'empty' || (value !== undefined && value !== ''))) {
|
|
118
118
|
filters.push({field, operator, value})
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -133,11 +133,11 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
133
133
|
|
|
134
134
|
protected applyUserFilter(filters: IDraxFieldFilter[], rbac: IRbac) {
|
|
135
135
|
|
|
136
|
-
if(rbac.hasSomePermission([this.permission.All, this.permission.ViewAll])) {
|
|
136
|
+
if (rbac.hasSomePermission([this.permission.All, this.permission.ViewAll])) {
|
|
137
137
|
return
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
if(this.userFilter && rbac.userId) {
|
|
140
|
+
if (this.userFilter && rbac.userId) {
|
|
141
141
|
filters.push({field: this.userField, operator: 'eq', value: rbac.userId})
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -155,10 +155,10 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
155
155
|
if (this.tenantAssert && rbac.hasTenant) {
|
|
156
156
|
|
|
157
157
|
//Si esta populado
|
|
158
|
-
if(item[this.tenantField]?._id){
|
|
158
|
+
if (item[this.tenantField]?._id) {
|
|
159
159
|
rbac.assertTenantId(item[this.tenantField]._id.toString())//
|
|
160
|
-
|
|
161
|
-
}else if(item[this.tenantField]){
|
|
160
|
+
//Si esta crudo
|
|
161
|
+
} else if (item[this.tenantField]) {
|
|
162
162
|
rbac.assertTenantId(item[this.tenantField].toString())
|
|
163
163
|
}
|
|
164
164
|
}
|
|
@@ -167,9 +167,9 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
167
167
|
protected assertUser(item: T, rbac: IRbac) {
|
|
168
168
|
|
|
169
169
|
if (this.userAssert) {
|
|
170
|
-
if(item[this.userField]?._id){
|
|
170
|
+
if (item[this.userField]?._id) {
|
|
171
171
|
rbac.assertUserId(item[this.userField]._id.toString())
|
|
172
|
-
}else if(item[this.userField]){
|
|
172
|
+
} else if (item[this.userField]) {
|
|
173
173
|
rbac.assertUserId(item[this.userField].toString())
|
|
174
174
|
}
|
|
175
175
|
}
|
|
@@ -193,10 +193,10 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
193
193
|
|
|
194
194
|
protected extractRequestData(request: FastifyRequest) {
|
|
195
195
|
return {
|
|
196
|
-
user:
|
|
196
|
+
user: {
|
|
197
197
|
id: request?.rbac?.userId,
|
|
198
198
|
username: request?.rbac?.username,
|
|
199
|
-
role:{
|
|
199
|
+
role: {
|
|
200
200
|
id: request?.rbac?.roleId,
|
|
201
201
|
name: request?.rbac?.roleName,
|
|
202
202
|
},
|
|
@@ -217,11 +217,10 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
async onCreated(request: CustomRequest, item:T){
|
|
220
|
+
async onCreated(request: CustomRequest, item: T) {
|
|
222
221
|
const requestData = this.extractRequestData(request)
|
|
223
222
|
const detail = `User ${requestData.user.username} created ${this.entityName}.`
|
|
224
|
-
const eventData
|
|
223
|
+
const eventData: IDraxCrudEvent = {
|
|
225
224
|
action: 'created',
|
|
226
225
|
entity: this.entityName,
|
|
227
226
|
postItem: item,
|
|
@@ -233,10 +232,10 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
233
232
|
this.eventEmitter.emitCrudEvent(eventData)
|
|
234
233
|
}
|
|
235
234
|
|
|
236
|
-
async onUpdated(request: CustomRequest, preItem: T, postItem:T){
|
|
235
|
+
async onUpdated(request: CustomRequest, preItem: T, postItem: T) {
|
|
237
236
|
const requestData = this.extractRequestData(request)
|
|
238
237
|
const detail = `User ${requestData.user.username} updated ${this.entityName}.`
|
|
239
|
-
const eventData
|
|
238
|
+
const eventData: IDraxCrudEvent = {
|
|
240
239
|
action: 'updated',
|
|
241
240
|
entity: this.entityName,
|
|
242
241
|
postItem: postItem,
|
|
@@ -251,7 +250,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
251
250
|
async onDeleted(request: CustomRequest, item: T) {
|
|
252
251
|
const requestData = this.extractRequestData(request)
|
|
253
252
|
const detail = `User ${requestData.user.username} deleted ${this.entityName}.`
|
|
254
|
-
const eventData
|
|
253
|
+
const eventData: IDraxCrudEvent = {
|
|
255
254
|
action: 'deleted',
|
|
256
255
|
entity: this.entityName,
|
|
257
256
|
postItem: null,
|
|
@@ -266,7 +265,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
266
265
|
async onExported(request: CustomRequest, response: IDraxExportResponse) {
|
|
267
266
|
const requestData = this.extractRequestData(request)
|
|
268
267
|
const detail = `User ${requestData.user.username} exported ${this.entityName}.`
|
|
269
|
-
const eventData
|
|
268
|
+
const eventData: IDraxCrudEvent = {
|
|
270
269
|
action: 'exported',
|
|
271
270
|
entity: this.entityName,
|
|
272
271
|
postItem: null,
|
|
@@ -278,11 +277,11 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
278
277
|
this.eventEmitter.emitCrudEvent(eventData)
|
|
279
278
|
}
|
|
280
279
|
|
|
281
|
-
async preCreate(request: CustomRequest, payload:any){
|
|
280
|
+
async preCreate(request: CustomRequest, payload: any) {
|
|
282
281
|
return payload
|
|
283
282
|
}
|
|
284
283
|
|
|
285
|
-
async postCreate(request: CustomRequest, item:T){
|
|
284
|
+
async postCreate(request: CustomRequest, item: T) {
|
|
286
285
|
return item
|
|
287
286
|
}
|
|
288
287
|
|
|
@@ -301,11 +300,11 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
301
300
|
}
|
|
302
301
|
}
|
|
303
302
|
|
|
304
|
-
async preUpdate(request: CustomRequest, payload:any):Promise<C>{
|
|
303
|
+
async preUpdate(request: CustomRequest, payload: any): Promise<C> {
|
|
305
304
|
return payload
|
|
306
305
|
}
|
|
307
306
|
|
|
308
|
-
async postUpdate(request: CustomRequest, item:T){
|
|
307
|
+
async postUpdate(request: CustomRequest, item: T) {
|
|
309
308
|
return item
|
|
310
309
|
}
|
|
311
310
|
|
|
@@ -334,12 +333,12 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
334
333
|
this.assertTenant(preItem, request.rbac)
|
|
335
334
|
|
|
336
335
|
//Definido el tenant en create no debe modificarse en un update
|
|
337
|
-
if(this.tenantSetter) {
|
|
336
|
+
if (this.tenantSetter) {
|
|
338
337
|
delete payload[this.tenantField]
|
|
339
338
|
}
|
|
340
339
|
|
|
341
340
|
//Definido el user en create no debe modificarse en un update
|
|
342
|
-
if(this.userSetter){
|
|
341
|
+
if (this.userSetter) {
|
|
343
342
|
delete payload[this.userField]
|
|
344
343
|
}
|
|
345
344
|
|
|
@@ -360,14 +359,45 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
360
359
|
}
|
|
361
360
|
}
|
|
362
361
|
|
|
363
|
-
async preUpdatePartial(request: CustomRequest, payload:any):Promise<C>{
|
|
362
|
+
async preUpdatePartial(request: CustomRequest, payload: any): Promise<C> {
|
|
364
363
|
return payload
|
|
365
364
|
}
|
|
366
365
|
|
|
367
|
-
async postUpdatePartial(request: CustomRequest, item:T){
|
|
366
|
+
async postUpdatePartial(request: CustomRequest, item: T) {
|
|
367
|
+
return item
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
//Sobrescribir este metodo para manipular items a devolver en operaciones de lectura
|
|
371
|
+
async postRead(request: CustomRequest, item: T) {
|
|
368
372
|
return item
|
|
369
373
|
}
|
|
370
374
|
|
|
375
|
+
protected isPaginateResult(result: unknown): result is IDraxPaginateResult<T> {
|
|
376
|
+
return typeof result === 'object' && result !== null && 'items' in result && Array.isArray(result.items)
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
async postReadItem(request: CustomRequest, item: T): Promise<T> {
|
|
380
|
+
return this.postRead(request, item)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async postReadItems(request: CustomRequest, items: T[]): Promise<T[]> {
|
|
384
|
+
if (Array.isArray(items)) {
|
|
385
|
+
return Promise.all(items.map(item => this.postRead(request, item)))
|
|
386
|
+
}
|
|
387
|
+
return items
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
async postReadPaginate(
|
|
391
|
+
request: CustomRequest,
|
|
392
|
+
pagination: IDraxPaginateResult<T>
|
|
393
|
+
): Promise<IDraxPaginateResult<T>> {
|
|
394
|
+
if (this.isPaginateResult(pagination)) {
|
|
395
|
+
pagination.items = await Promise.all(pagination.items.map(item => this.postRead(request, item)))
|
|
396
|
+
}
|
|
397
|
+
return pagination
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
|
|
371
401
|
async updatePartial(request: CustomRequest, reply: FastifyReply) {
|
|
372
402
|
try {
|
|
373
403
|
request.rbac.assertPermission(this.permission.Update)
|
|
@@ -394,12 +424,12 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
394
424
|
this.assertTenant(preItem, request.rbac)
|
|
395
425
|
|
|
396
426
|
//Definido el tenant en el create no debe modificarse en un update
|
|
397
|
-
if(this.tenantSetter) {
|
|
427
|
+
if (this.tenantSetter) {
|
|
398
428
|
delete payload[this.tenantField]
|
|
399
429
|
}
|
|
400
430
|
|
|
401
431
|
//Definido el user en el create no debe modificarse en un update
|
|
402
|
-
if(this.userSetter){
|
|
432
|
+
if (this.userSetter) {
|
|
403
433
|
delete payload[this.userField]
|
|
404
434
|
}
|
|
405
435
|
|
|
@@ -419,11 +449,11 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
419
449
|
}
|
|
420
450
|
}
|
|
421
451
|
|
|
422
|
-
async preDelete(request: CustomRequest, item:T){
|
|
452
|
+
async preDelete(request: CustomRequest, item: T) {
|
|
423
453
|
return item
|
|
424
454
|
}
|
|
425
455
|
|
|
426
|
-
async postDelete(request: CustomRequest, item:T){
|
|
456
|
+
async postDelete(request: CustomRequest, item: T) {
|
|
427
457
|
return item
|
|
428
458
|
}
|
|
429
459
|
|
|
@@ -491,6 +521,8 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
491
521
|
|
|
492
522
|
this.assertTenant(item, request.rbac)
|
|
493
523
|
|
|
524
|
+
item = await this.postReadItem(request, item)
|
|
525
|
+
|
|
494
526
|
return item
|
|
495
527
|
} catch (e) {
|
|
496
528
|
this.handleError(e, reply)
|
|
@@ -511,6 +543,8 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
511
543
|
throw new NotFoundError()
|
|
512
544
|
}
|
|
513
545
|
|
|
546
|
+
items = await this.postReadItems(request, items)
|
|
547
|
+
|
|
514
548
|
return items
|
|
515
549
|
} catch (e) {
|
|
516
550
|
this.handleError(e, reply)
|
|
@@ -535,6 +569,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
535
569
|
|
|
536
570
|
let items = await this.service.find({search, filters, order, orderBy, limit})
|
|
537
571
|
|
|
572
|
+
items = await this.postReadItems(request, items)
|
|
538
573
|
|
|
539
574
|
return items
|
|
540
575
|
} catch (e) {
|
|
@@ -553,6 +588,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
553
588
|
|
|
554
589
|
let item = await this.service.findOne({search, filters})
|
|
555
590
|
|
|
591
|
+
item = await this.postReadItem(request, item)
|
|
556
592
|
|
|
557
593
|
return item
|
|
558
594
|
} catch (e) {
|
|
@@ -577,9 +613,8 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
577
613
|
|
|
578
614
|
let items = await this.service.findBy(field, value, limit, filters)
|
|
579
615
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
// }
|
|
616
|
+
|
|
617
|
+
items = await this.postReadItems(request, items)
|
|
583
618
|
|
|
584
619
|
return items
|
|
585
620
|
} catch (e) {
|
|
@@ -603,7 +638,8 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
603
638
|
|
|
604
639
|
let item = await this.service.findOneBy(field, value, filters)
|
|
605
640
|
|
|
606
|
-
|
|
641
|
+
|
|
642
|
+
item = await this.postReadItem(request, item)
|
|
607
643
|
|
|
608
644
|
return item
|
|
609
645
|
} catch (e) {
|
|
@@ -621,8 +657,9 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
621
657
|
|
|
622
658
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
623
659
|
|
|
624
|
-
let
|
|
625
|
-
|
|
660
|
+
let items = await this.service.search(search, limit, filters)
|
|
661
|
+
items = await this.postReadItems(request, items)
|
|
662
|
+
return items
|
|
626
663
|
} catch (e) {
|
|
627
664
|
this.handleError(e, reply)
|
|
628
665
|
}
|
|
@@ -645,9 +682,9 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
645
682
|
const filters: IDraxFieldFilter[] = this.parseFilters(request.query.filters)
|
|
646
683
|
this.applyUserAndTenantFilters(filters, request.rbac);
|
|
647
684
|
|
|
648
|
-
// console.log("paginate filters",filters)
|
|
649
685
|
|
|
650
686
|
let paginateResult = await this.service.paginate({page, limit, orderBy, order, search, filters})
|
|
687
|
+
paginateResult = await this.postReadPaginate(request, paginateResult)
|
|
651
688
|
return paginateResult
|
|
652
689
|
} catch (e) {
|
|
653
690
|
this.handleError(e, reply)
|
|
@@ -655,8 +692,6 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
655
692
|
}
|
|
656
693
|
|
|
657
694
|
|
|
658
|
-
|
|
659
|
-
|
|
660
695
|
async export(request: CustomRequest, reply: FastifyReply) {
|
|
661
696
|
try {
|
|
662
697
|
request.rbac.assertPermission(this.permission.View)
|
|
@@ -695,7 +730,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
|
|
|
695
730
|
|
|
696
731
|
const url = `${this.baseURL}/api/file/${exportPath}/${year}/${month}/${result.fileName}`
|
|
697
732
|
|
|
698
|
-
const response
|
|
733
|
+
const response: IDraxExportResponse = {
|
|
699
734
|
url: url,
|
|
700
735
|
rowCount: result.rowCount,
|
|
701
736
|
time: result.time,
|
|
@@ -317,7 +317,7 @@ class AbstractSqliteRepository<T, C, U> implements IDraxCrud<T, C, U> {
|
|
|
317
317
|
total: rCount.count,
|
|
318
318
|
items
|
|
319
319
|
}
|
|
320
|
-
console.log('Pagination result:', JSON.stringify(pagination,null,4))
|
|
320
|
+
// console.log('Pagination result:', JSON.stringify(pagination,null,4))
|
|
321
321
|
return pagination
|
|
322
322
|
}
|
|
323
323
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { describe, it, beforeAll, afterAll, expect } from "vitest"
|
|
1
|
+
import { describe, it, beforeAll, afterAll, afterEach, expect, vi } from "vitest"
|
|
2
2
|
import { PersonFastifyRoutes } from '../people/routes/PersonRoutes'
|
|
3
3
|
import { PersonPermissions } from '../people/permissions/PersonPermissions'
|
|
4
|
+
import { PersonController } from '../people/controllers/PersonController.js'
|
|
4
5
|
|
|
5
6
|
import type { IPersonBase } from '../people/interfaces/IPerson'
|
|
6
7
|
|
|
@@ -32,6 +33,10 @@ describe("Person Controller Test", function () {
|
|
|
32
33
|
return
|
|
33
34
|
})
|
|
34
35
|
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
vi.restoreAllMocks()
|
|
38
|
+
})
|
|
39
|
+
|
|
35
40
|
// Test users are logged in and get their details
|
|
36
41
|
it("Me Admin Root", async () => {
|
|
37
42
|
const { accessToken } = await testSetup.rootUserLogin()
|
|
@@ -105,6 +110,34 @@ describe("Person Controller Test", function () {
|
|
|
105
110
|
expect(getEntity.fullname).toBe("Test Person")
|
|
106
111
|
})
|
|
107
112
|
|
|
113
|
+
it("should run postCreate interceptor after creating a person", async () => {
|
|
114
|
+
const { accessToken } = await testSetup.rootUserLogin()
|
|
115
|
+
await testSetup.dropCollection('Person')
|
|
116
|
+
|
|
117
|
+
const postCreateSpy = vi
|
|
118
|
+
.spyOn(PersonController.prototype, 'postCreate')
|
|
119
|
+
.mockImplementation(async (_request, item) => ({
|
|
120
|
+
...item,
|
|
121
|
+
fullname: `${item.fullname} [postCreate]`
|
|
122
|
+
}))
|
|
123
|
+
|
|
124
|
+
const resp = await testSetup.fastifyInstance.inject({
|
|
125
|
+
method: 'POST',
|
|
126
|
+
url: '/api/person',
|
|
127
|
+
payload: {
|
|
128
|
+
fullname: "Create Hook",
|
|
129
|
+
money: 100,
|
|
130
|
+
address: defaultAddress
|
|
131
|
+
},
|
|
132
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const person = await resp.json()
|
|
136
|
+
expect(resp.statusCode).toBe(200)
|
|
137
|
+
expect(postCreateSpy).toHaveBeenCalledTimes(1)
|
|
138
|
+
expect(person.fullname).toBe("Create Hook [postCreate]")
|
|
139
|
+
})
|
|
140
|
+
|
|
108
141
|
// 2. Create and Update (Full Update - PUT)
|
|
109
142
|
it("should create and update a person and finally find by id", async () => {
|
|
110
143
|
const { accessToken } = await testSetup.rootUserLogin()
|
|
@@ -152,6 +185,47 @@ describe("Person Controller Test", function () {
|
|
|
152
185
|
expect(verifiedEntity.money).toBe(150)
|
|
153
186
|
})
|
|
154
187
|
|
|
188
|
+
it("should run postUpdate interceptor after updating a person", async () => {
|
|
189
|
+
const { accessToken } = await testSetup.rootUserLogin()
|
|
190
|
+
await testSetup.dropCollection('Person')
|
|
191
|
+
|
|
192
|
+
const createResp = await testSetup.fastifyInstance.inject({
|
|
193
|
+
method: 'POST',
|
|
194
|
+
url: '/api/person',
|
|
195
|
+
payload: {
|
|
196
|
+
fullname: "Update Hook",
|
|
197
|
+
money: 100,
|
|
198
|
+
address: defaultAddress
|
|
199
|
+
},
|
|
200
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
const createdEntity = await createResp.json()
|
|
204
|
+
|
|
205
|
+
const postUpdateSpy = vi
|
|
206
|
+
.spyOn(PersonController.prototype, 'postUpdate')
|
|
207
|
+
.mockImplementation(async (_request, item) => ({
|
|
208
|
+
...item,
|
|
209
|
+
fullname: `${item.fullname} [postUpdate]`
|
|
210
|
+
}))
|
|
211
|
+
|
|
212
|
+
const updateResp = await testSetup.fastifyInstance.inject({
|
|
213
|
+
method: 'PUT',
|
|
214
|
+
url: `/api/person/${createdEntity._id}`,
|
|
215
|
+
payload: {
|
|
216
|
+
fullname: "Updated Hook",
|
|
217
|
+
money: 250,
|
|
218
|
+
address: defaultAddress
|
|
219
|
+
},
|
|
220
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
const updatedEntity = await updateResp.json()
|
|
224
|
+
expect(updateResp.statusCode).toBe(200)
|
|
225
|
+
expect(postUpdateSpy).toHaveBeenCalledTimes(1)
|
|
226
|
+
expect(updatedEntity.fullname).toBe("Updated Hook [postUpdate]")
|
|
227
|
+
})
|
|
228
|
+
|
|
155
229
|
// 3. Create and Partial Update (PATCH)
|
|
156
230
|
it("should create and update partial a person and finally find by id", async () => {
|
|
157
231
|
const { accessToken } = await testSetup.rootUserLogin()
|
|
@@ -192,6 +266,79 @@ describe("Person Controller Test", function () {
|
|
|
192
266
|
expect(verifiedEntity.money).toBe(120)
|
|
193
267
|
})
|
|
194
268
|
|
|
269
|
+
it("should run postUpdatePartial interceptor after patching a person", async () => {
|
|
270
|
+
const { accessToken } = await testSetup.rootUserLogin()
|
|
271
|
+
await testSetup.dropCollection('Person')
|
|
272
|
+
|
|
273
|
+
const createResp = await testSetup.fastifyInstance.inject({
|
|
274
|
+
method: 'POST',
|
|
275
|
+
url: '/api/person',
|
|
276
|
+
payload: {
|
|
277
|
+
fullname: "Patch Hook",
|
|
278
|
+
money: 120,
|
|
279
|
+
address: defaultAddress
|
|
280
|
+
},
|
|
281
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
const createdEntity = await createResp.json()
|
|
285
|
+
|
|
286
|
+
const postUpdatePartialSpy = vi
|
|
287
|
+
.spyOn(PersonController.prototype, 'postUpdatePartial')
|
|
288
|
+
.mockImplementation(async (_request, item) => ({
|
|
289
|
+
...item,
|
|
290
|
+
fullname: `${item.fullname} [postUpdatePartial]`
|
|
291
|
+
}))
|
|
292
|
+
|
|
293
|
+
const patchResp = await testSetup.fastifyInstance.inject({
|
|
294
|
+
method: 'PATCH',
|
|
295
|
+
url: `/api/person/${createdEntity._id}`,
|
|
296
|
+
payload: { fullname: "Patched Hook" },
|
|
297
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
const patchedEntity = await patchResp.json()
|
|
301
|
+
expect(patchResp.statusCode).toBe(200)
|
|
302
|
+
expect(postUpdatePartialSpy).toHaveBeenCalledTimes(1)
|
|
303
|
+
expect(patchedEntity.fullname).toBe("Patched Hook [postUpdatePartial]")
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
it("should run postRead interceptor when reading a person", async () => {
|
|
307
|
+
const { accessToken } = await testSetup.rootUserLogin()
|
|
308
|
+
await testSetup.dropCollection('Person')
|
|
309
|
+
|
|
310
|
+
const createResp = await testSetup.fastifyInstance.inject({
|
|
311
|
+
method: 'POST',
|
|
312
|
+
url: '/api/person',
|
|
313
|
+
payload: {
|
|
314
|
+
fullname: "Read Hook",
|
|
315
|
+
money: 80,
|
|
316
|
+
address: defaultAddress
|
|
317
|
+
},
|
|
318
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
const createdEntity = await createResp.json()
|
|
322
|
+
|
|
323
|
+
const postReadSpy = vi
|
|
324
|
+
.spyOn(PersonController.prototype, 'postRead')
|
|
325
|
+
.mockImplementation(async (_request, item) => ({
|
|
326
|
+
...item,
|
|
327
|
+
fullname: `${item.fullname} [postRead]`
|
|
328
|
+
}))
|
|
329
|
+
|
|
330
|
+
const getResp = await testSetup.fastifyInstance.inject({
|
|
331
|
+
method: 'GET',
|
|
332
|
+
url: `/api/person/${createdEntity._id}`,
|
|
333
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
const person = await getResp.json()
|
|
337
|
+
expect(getResp.statusCode).toBe(200)
|
|
338
|
+
expect(postReadSpy).toHaveBeenCalledTimes(1)
|
|
339
|
+
expect(person.fullname).toBe("Read Hook [postRead]")
|
|
340
|
+
})
|
|
341
|
+
|
|
195
342
|
// 4. Create and Delete
|
|
196
343
|
it("should create and delete a person", async () => {
|
|
197
344
|
const { accessToken } = await testSetup.rootUserLogin()
|