@solidstarters/solid-core 1.2.34 → 1.2.37
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/services/crud-helper.service.d.ts +2 -1
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +5 -0
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts +5 -2
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +61 -6
- package/dist/services/crud.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/services/crud-helper.service.ts +6 -1
- package/src/services/crud.service.ts +83 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidstarters/solid-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.37",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -141,7 +141,7 @@ export class CrudHelperService {
|
|
|
141
141
|
}, {});
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
|
|
144
|
+
normalize(value: string | string[]): string[] {
|
|
145
145
|
if (!value) return [];// if the value is nullish, then return an empty array
|
|
146
146
|
return Array.isArray(value) ? value : [value]; // if the value is an array, return it as is, otherwise return it as an array
|
|
147
147
|
}
|
|
@@ -312,6 +312,11 @@ export class CrudHelperService {
|
|
|
312
312
|
const matchingPermssions = activeUser.permissions.filter((p) => permissionNames.includes(p));
|
|
313
313
|
return matchingPermssions.length > 0
|
|
314
314
|
}
|
|
315
|
+
hasRecoverPermissionOnModel = (activeUser: ActiveUserData, modelName: string) => {
|
|
316
|
+
const permissionNames = [`${classify(modelName)}Controller.recover`, `${classify(modelName)}Controller.recoverMany`];
|
|
317
|
+
const matchingPermssions = activeUser.permissions.filter((p) => permissionNames.includes(p));
|
|
318
|
+
return matchingPermssions.length > 0
|
|
319
|
+
}
|
|
315
320
|
|
|
316
321
|
|
|
317
322
|
|
|
@@ -428,13 +428,19 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
+
// Exclude one-to-many and many-to-one relations from the initial filter query, since they will be queried separately
|
|
432
|
+
const relationsExcludedFromInitialQuery = this.relationsExcludedFromInitialQuery(model, basicFilterDto.populate);
|
|
433
|
+
basicFilterDto = this.getRevisedFilterDto(basicFilterDto, relationsExcludedFromInitialQuery);
|
|
434
|
+
|
|
431
435
|
// Create above query on pincode table using query builder
|
|
432
436
|
var qb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias)
|
|
433
437
|
qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);
|
|
434
|
-
|
|
438
|
+
|
|
435
439
|
if (basicFilterDto.groupBy) {
|
|
440
|
+
const relationsExcludedFromInitialQuery = this.relationsExcludedFromInitialQuery(model, groupFilter.populate);
|
|
441
|
+
groupFilter = this.getRevisedFilterDto(groupFilter, relationsExcludedFromInitialQuery);
|
|
436
442
|
// Get the records and the count
|
|
437
|
-
const { groupMeta, groupRecords } = await this.handleGroupFind(qb, groupFilter, populateGroup, alias, populateMedia);
|
|
443
|
+
const { groupMeta, groupRecords } = await this.handleGroupFind(qb, groupFilter, populateGroup, alias, populateMedia, relationsExcludedFromInitialQuery);
|
|
438
444
|
return {
|
|
439
445
|
groupMeta,
|
|
440
446
|
groupRecords,
|
|
@@ -442,7 +448,7 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
442
448
|
}
|
|
443
449
|
else {
|
|
444
450
|
// Get the records and the count
|
|
445
|
-
const { meta, records } = await this.handleNonGroupFind(qb, populateMedia, offset, limit);
|
|
451
|
+
const { meta, records } = await this.handleNonGroupFind(qb, populateMedia, offset, limit, alias, relationsExcludedFromInitialQuery);
|
|
446
452
|
return {
|
|
447
453
|
meta,
|
|
448
454
|
records,
|
|
@@ -450,9 +456,28 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
450
456
|
}
|
|
451
457
|
}
|
|
452
458
|
|
|
453
|
-
private
|
|
459
|
+
private getRevisedFilterDto(basicFilterDto: BasicFilterDto, relationsExcludedFromInitialQuery: string[]): BasicFilterDto {
|
|
460
|
+
const normalizedPopulate = this.crudHelperService.normalize(basicFilterDto.populate);
|
|
461
|
+
if (normalizedPopulate.length === 0 || relationsExcludedFromInitialQuery.length === 0) return basicFilterDto;
|
|
462
|
+
return { ...basicFilterDto, populate: normalizedPopulate.filter(populate => !relationsExcludedFromInitialQuery.includes(populate)) };
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
private relationsExcludedFromInitialQuery(model: ModelMetadata, relationsToBePopulated: string[] = []): string[] {
|
|
466
|
+
const relationToBeExcluded =
|
|
467
|
+
model.fields
|
|
468
|
+
.filter(field => field.type === 'relation' && [RelationType.manyTomany, RelationType.oneToMany].includes(field.relationType as RelationType))
|
|
469
|
+
.map(field => field.name);
|
|
470
|
+
return relationsToBePopulated.filter(relation => relationToBeExcluded.includes(relation));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
private async handleNonGroupFind(qb: SelectQueryBuilder<T>, populateMedia: string[], offset: number, limit: number, alias: string, relationsExcludedFromInitialQuery: string[]) {
|
|
454
474
|
const [entities, count] = await qb.getManyAndCount();
|
|
455
475
|
|
|
476
|
+
// Populate the excluded relations for the entities
|
|
477
|
+
if (relationsExcludedFromInitialQuery.length > 0) {
|
|
478
|
+
await this.populateExcludedRelations(entities, relationsExcludedFromInitialQuery, alias);
|
|
479
|
+
}
|
|
480
|
+
|
|
456
481
|
// Populate the entity with the media
|
|
457
482
|
if (populateMedia && populateMedia.length > 0) {
|
|
458
483
|
await this.handlePopulateMedia(populateMedia, entities);
|
|
@@ -461,7 +486,36 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
461
486
|
return this.wrapFindResponse(offset, limit, count, entities);
|
|
462
487
|
}
|
|
463
488
|
|
|
464
|
-
private async
|
|
489
|
+
private async populateExcludedRelations(entities: T[], relationsExcludedFromInitialQuery: string[], alias: string) {
|
|
490
|
+
//@ts-ignore
|
|
491
|
+
const ids = entities.map(entity => entity.id);
|
|
492
|
+
|
|
493
|
+
// Fire a query to get the records from the relation entity which match the ids
|
|
494
|
+
// Create a map with key as the entity id and value as the qb records
|
|
495
|
+
const relationEntitiesMap = {};
|
|
496
|
+
for (const relation of relationsExcludedFromInitialQuery) {
|
|
497
|
+
const qb = this.repo.createQueryBuilder(`${alias}`)
|
|
498
|
+
.leftJoinAndSelect(`${alias}.${relation}`, relation)
|
|
499
|
+
.where(`${alias}.id IN (:...ids)`, { ids })
|
|
500
|
+
// .limit(DEFAULT_LIMIT)
|
|
501
|
+
// .offset(DEFAULT_OFFSET);
|
|
502
|
+
const relationEntities = await qb.getMany();
|
|
503
|
+
relationEntitiesMap[relation] = relationEntities;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Iterate over the map and assign the relation entities to the entity
|
|
507
|
+
for (const relation of relationsExcludedFromInitialQuery) {
|
|
508
|
+
for (const entity of entities) {
|
|
509
|
+
const entityRelations = relationEntitiesMap[relation]
|
|
510
|
+
//@ts-ignore
|
|
511
|
+
.filter((joinedEntity: T) => joinedEntity.id === entity.id)
|
|
512
|
+
.flatMap((joinedEntity: T) => joinedEntity[relation]);
|
|
513
|
+
entity[relation] = entityRelations;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
private async handleGroupFind(qb: SelectQueryBuilder<T>, groupFilter: BasicFilterDto, populateGroup: boolean, alias: string, populateMedia: string[], relationsExcludedFromInitialQuery: string[]) {
|
|
465
519
|
const groupByResult = await qb.getRawMany();
|
|
466
520
|
|
|
467
521
|
const groupMeta = [];
|
|
@@ -470,15 +524,14 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
470
524
|
for (const group of groupByResult) {
|
|
471
525
|
if (populateGroup) {
|
|
472
526
|
let groupByQb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias);
|
|
473
|
-
// For the group by records, apply the basic filter
|
|
474
|
-
// const basicFilterDto = {
|
|
475
|
-
// limit: DEFAULT_LIMIT,
|
|
476
|
-
// offset: DEFAULT_OFFSET,
|
|
477
|
-
// };
|
|
478
527
|
groupByQb = this.crudHelperService.buildFilterQuery(groupByQb, groupFilter, alias);
|
|
479
528
|
groupByQb = this.crudHelperService.buildGroupByRecordsQuery(groupByQb, group, alias);
|
|
480
529
|
const [entities, count] = await groupByQb.getManyAndCount();
|
|
481
530
|
|
|
531
|
+
// Populate the excluded relations for the entities
|
|
532
|
+
if (relationsExcludedFromInitialQuery.length > 0) {
|
|
533
|
+
await this.populateExcludedRelations(entities, relationsExcludedFromInitialQuery, alias);
|
|
534
|
+
}
|
|
482
535
|
|
|
483
536
|
// Populate the entity with the media
|
|
484
537
|
if (populateMedia && populateMedia.length > 0) {
|
|
@@ -701,8 +754,17 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
701
754
|
// return removedEntities
|
|
702
755
|
}
|
|
703
756
|
|
|
704
|
-
async recover(id: number) {
|
|
757
|
+
async recover(id: number,solidRequestContext: any = {}) {
|
|
705
758
|
try {
|
|
759
|
+
const loadedmodel = await this.loadModel();
|
|
760
|
+
// Check wheather user has update permission for model
|
|
761
|
+
if (solidRequestContext.activeUser) {
|
|
762
|
+
const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
|
|
763
|
+
if (!hasPermission) {
|
|
764
|
+
throw new BadRequestException('Forbidden');
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
706
768
|
const softDeletedRows = await this.repo.findOne({
|
|
707
769
|
where: {
|
|
708
770
|
//@ts-ignore
|
|
@@ -732,8 +794,17 @@ export class CRUDService<T> { //Add two generic value i.e Person,CreatePersonDto
|
|
|
732
794
|
}
|
|
733
795
|
}
|
|
734
796
|
|
|
735
|
-
async recoverMany(ids: number[]) {
|
|
797
|
+
async recoverMany(ids: number[],solidRequestContext: any = {}) {
|
|
736
798
|
try {
|
|
799
|
+
const loadedmodel = await this.loadModel();
|
|
800
|
+
// Check wheather user has update permission for model
|
|
801
|
+
if (solidRequestContext.activeUser) {
|
|
802
|
+
const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
|
|
803
|
+
if (!hasPermission) {
|
|
804
|
+
throw new BadRequestException('Forbidden');
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
|
|
737
808
|
if (!ids || ids.length === 0) {
|
|
738
809
|
throw new Error("No IDs provided for recovery.");
|
|
739
810
|
}
|