@solidstarters/solid-core 1.2.54 → 1.2.57

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.
Files changed (48) hide show
  1. package/dist/controllers/authentication.controller.d.ts +7 -35
  2. package/dist/controllers/authentication.controller.d.ts.map +1 -1
  3. package/dist/controllers/field-metadata.controller.js +1 -1
  4. package/dist/controllers/media-storage-provider-metadata.controller.d.ts +1 -1
  5. package/dist/controllers/media-storage-provider-metadata.controller.js +3 -3
  6. package/dist/controllers/module-metadata.controller.d.ts +1 -1
  7. package/dist/controllers/module-metadata.controller.js +2 -2
  8. package/dist/helpers/schematic.service.d.ts +1 -0
  9. package/dist/helpers/schematic.service.d.ts.map +1 -1
  10. package/dist/helpers/schematic.service.js +3 -0
  11. package/dist/helpers/schematic.service.js.map +1 -1
  12. package/dist/seeders/module-metadata-seeder.service.js +1 -1
  13. package/dist/seeders/seed-data/solid-core-metadata.json +6 -6
  14. package/dist/services/authentication.service.d.ts +7 -35
  15. package/dist/services/authentication.service.d.ts.map +1 -1
  16. package/dist/services/authentication.service.js +7 -1
  17. package/dist/services/authentication.service.js.map +1 -1
  18. package/dist/services/crud-helper.service.d.ts +3 -0
  19. package/dist/services/crud-helper.service.d.ts.map +1 -1
  20. package/dist/services/crud-helper.service.js +30 -10
  21. package/dist/services/crud-helper.service.js.map +1 -1
  22. package/dist/services/crud.service.d.ts +0 -4
  23. package/dist/services/crud.service.d.ts.map +1 -1
  24. package/dist/services/crud.service.js +6 -60
  25. package/dist/services/crud.service.js.map +1 -1
  26. package/dist/services/field-metadata.service.d.ts +1 -1
  27. package/dist/services/field-metadata.service.d.ts.map +1 -1
  28. package/dist/services/field-metadata.service.js +2 -3
  29. package/dist/services/field-metadata.service.js.map +1 -1
  30. package/dist/services/media-storage-provider-metadata.service.d.ts +1 -1
  31. package/dist/services/media-storage-provider-metadata.service.js +1 -1
  32. package/dist/services/model-metadata.service.d.ts.map +1 -1
  33. package/dist/services/model-metadata.service.js +6 -5
  34. package/dist/services/model-metadata.service.js.map +1 -1
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +1 -1
  37. package/src/controllers/field-metadata.controller.ts +1 -1
  38. package/src/controllers/media-storage-provider-metadata.controller.ts +2 -2
  39. package/src/controllers/module-metadata.controller.ts +1 -1
  40. package/src/helpers/schematic.service.ts +12 -8
  41. package/src/seeders/module-metadata-seeder.service.ts +1 -1
  42. package/src/seeders/seed-data/solid-core-metadata.json +6 -6
  43. package/src/services/authentication.service.ts +8 -1
  44. package/src/services/crud-helper.service.ts +39 -13
  45. package/src/services/crud.service.ts +6 -79
  46. package/src/services/field-metadata.service.ts +2 -4
  47. package/src/services/media-storage-provider-metadata.service.ts +1 -1
  48. package/src/services/model-metadata.service.ts +7 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidstarters/solid-core",
3
- "version": "1.2.54",
3
+ "version": "1.2.57",
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",
@@ -64,7 +64,7 @@ export class FieldMetadataController {
64
64
  @ApiBearerAuth("jwt")
65
65
  @Delete(':id')
66
66
  async delete(@Param('id') id: number) {
67
- return this.fieldMetadataService.remove(id);
67
+ return this.fieldMetadataService.delete(id);
68
68
  }
69
69
 
70
70
 
@@ -57,8 +57,8 @@ export class MediaStorageProviderMetadataController {
57
57
 
58
58
  @ApiBearerAuth("jwt")
59
59
  @Delete(':id')
60
- remove(@Param('id') id: number) {
61
- return this.mediaStorageProviderService.remove(id);
60
+ delete(@Param('id') id: number) {
61
+ return this.mediaStorageProviderService.delete(id);
62
62
  }
63
63
 
64
64
  }
@@ -82,7 +82,7 @@ export class ModuleMetadataController {
82
82
 
83
83
  @ApiBearerAuth("jwt")
84
84
  @Delete(':id')
85
- remove(@Param('id') id: number) {
85
+ delete(@Param('id') id: number) {
86
86
  return this.moduleMetadataService.remove(id);
87
87
  }
88
88
  }
@@ -15,6 +15,7 @@ type FieldOptions = {
15
15
  fields: any[]; //FIXME This type can be improved
16
16
  modelEnableSoftDelete?: boolean;
17
17
  parentModel?: string;
18
+ parentModule?: string;
18
19
  };
19
20
  export const REMOVE_FIELDS_COMMAND = 'remove-fields';
20
21
  export const REFRESH_MODEL_COMMAND = 'refresh-model';
@@ -31,7 +32,7 @@ enum SYSTEM_FIELDS_TO_IGNORE_FOR_CODE_GENERATION {
31
32
  export class SchematicService {
32
33
  private readonly logger = new Logger(SchematicService.name);
33
34
  private readonly SCHEMATIC_PROJECT = '@solidstarters/solid-code-builder';
34
- constructor(private readonly commandService: CommandService) {}
35
+ constructor(private readonly commandService: CommandService) { }
35
36
 
36
37
  async executeSchematicCommand(
37
38
  command: string,
@@ -62,7 +63,7 @@ export class SchematicService {
62
63
  if (fieldOptions.table) {
63
64
  modelCommand += ` --table=${fieldOptions.table}`;
64
65
  }
65
-
66
+
66
67
  if (fieldOptions.dataSource) {
67
68
  modelCommand += ` --data-source=${fieldOptions.dataSource}`;
68
69
  }
@@ -70,26 +71,29 @@ export class SchematicService {
70
71
  if (fieldOptions.modelEnableSoftDelete) {
71
72
  modelCommand += ` --model-enable-soft-delete=${fieldOptions.modelEnableSoftDelete}`;
72
73
  }
73
-
74
+
74
75
  if (fieldOptions.parentModel) {
75
76
  modelCommand += ` --parent-model=${fieldOptions.parentModel}`;
76
77
  }
77
-
78
+ if (fieldOptions.parentModule) {
79
+ modelCommand += ` --parent-module=${fieldOptions.parentModule}`;
80
+ }
81
+
78
82
  let fieldCommand = fieldOptions.fields
79
83
  .filter((field) => {
80
84
  return !Object.values(SYSTEM_FIELDS_TO_IGNORE_FOR_CODE_GENERATION).includes(field.name);
81
- })
85
+ })
82
86
  .map((field) => {
83
87
  return `--fields='${JSON.stringify(field)}'`;
84
88
  })
85
89
  .join(' ');
86
- const schematicCommand = modelCommand + ' ' + fieldCommand;
90
+ const schematicCommand = modelCommand + ' ' + fieldCommand;
87
91
  // console.log('schematicCommand', schematicCommand);
88
92
  return schematicCommand;
89
93
  } else if (command === ADD_MODULE_COMMAND) {
90
94
  const moduleOptions = options as GenerateModuleOptions;
91
95
  // console.log('moduleOptions', moduleOptions);
92
- const schematicCommand = ` ${baseCommand} --module=${moduleOptions.module}`;
96
+ const schematicCommand = ` ${baseCommand} --module=${moduleOptions.module}`;
93
97
  // console.log('schematicCommand', schematicCommand);
94
98
  this.logger.debug('schematicCommand', schematicCommand);
95
99
  return schematicCommand;
@@ -97,5 +101,5 @@ export class SchematicService {
97
101
  throw new Error('Schematic command not supported.');
98
102
  }
99
103
  }
100
-
104
+
101
105
  }
@@ -208,7 +208,7 @@ export class ModuleMetadataSeederService {
208
208
  this.logger.debug(`[End] Processing security rules for ${moduleMetadata.name}`);
209
209
 
210
210
  // List Of Values
211
- this.logger.debug(`[Start] Processing security rules for ${moduleMetadata.name}`);
211
+ this.logger.debug(`[Start] Processing List Of Values for ${moduleMetadata.name}`);
212
212
  const listOfValues: CreateListOfValuesDto[] = overallMetadata.listOfValues;
213
213
  await this.seedListOfValues(listOfValues);
214
214
  this.logger.debug(`[End] Processing List Of Values for ${moduleMetadata.name}`);
@@ -5355,7 +5355,7 @@
5355
5355
  {
5356
5356
  "type": "field",
5357
5357
  "attrs": {
5358
- "name": "view"
5358
+ "name": "viewMetadata"
5359
5359
  }
5360
5360
  }
5361
5361
  ]
@@ -5813,7 +5813,7 @@
5813
5813
  "type": "field",
5814
5814
  "attrs": {
5815
5815
  "name": "roles",
5816
- "renderMode": "checkbox",
5816
+ "widget": "checkbox",
5817
5817
  "inlineCreateAutoSave": "true",
5818
5818
  "renderModeCheckboxPreprocessor": "MenuItemMetadataRolesFormFieldPreprocessor",
5819
5819
  "inlineCreate": "true",
@@ -5899,7 +5899,7 @@
5899
5899
  "type": "field",
5900
5900
  "attrs": {
5901
5901
  "name": "relativeUri",
5902
- "renderMode": "image",
5902
+ "widget": "image",
5903
5903
  "isSearchable": true
5904
5904
  }
5905
5905
  },
@@ -5986,7 +5986,7 @@
5986
5986
  "attrs": {
5987
5987
  "name": "relativeUri",
5988
5988
  "label": "relativeUri",
5989
- "renderMode": "image"
5989
+ "widget": "image"
5990
5990
  }
5991
5991
  },
5992
5992
  {
@@ -7029,7 +7029,7 @@
7029
7029
  "attrs": {
7030
7030
  "name": "permissions",
7031
7031
  "isSearchable": true,
7032
- "renderMode": "checkbox",
7032
+ "widget": "checkbox",
7033
7033
  "inlineCreate": "true"
7034
7034
  }
7035
7035
  },
@@ -7122,7 +7122,7 @@
7122
7122
  "type": "field",
7123
7123
  "attrs": {
7124
7124
  "name": "permissions",
7125
- "renderMode": "inputSwitch",
7125
+ "widget": "inputSwitch",
7126
7126
  "showLabel": false
7127
7127
  }
7128
7128
  }
@@ -1009,7 +1009,14 @@ export class AuthenticationService {
1009
1009
  const tokens = await this.generateTokens(user);
1010
1010
 
1011
1011
  const response = {
1012
- ...user,
1012
+ user: {
1013
+ email: user.email,
1014
+ mobile: user.mobile,
1015
+ username: user.username,
1016
+ // forcePasswordChange: user.forcePasswordChange,
1017
+ id: user.id,
1018
+ roles: user.roles.map((role, idx, roles) => role.name)
1019
+ },
1013
1020
  ...tokens
1014
1021
  }
1015
1022
  return response;
@@ -52,7 +52,8 @@ export class CrudHelperService {
52
52
  return;
53
53
  }
54
54
  else { // Recursively call the applyFilters method to handle nested conditions
55
- selectQb.leftJoin(`${alias}.${key}`, key);
55
+ const joinField = `${alias}.${key}`;
56
+ if (!this.isRelationJoined(selectQb, joinField)) selectQb.leftJoin(joinField, key);
56
57
  this.applyFilters(qb, primaryFilterObj, key, selectQb);
57
58
  }
58
59
  });
@@ -150,6 +151,11 @@ export class CrudHelperService {
150
151
  return queryBuilder.expressionMap.joinAttributes.some(join => join.entityOrProperty === joinProperty);
151
152
  }
152
153
 
154
+ private hasJoins(queryBuilder: SelectQueryBuilder<any>): boolean {
155
+ return queryBuilder.expressionMap.joinAttributes.length > 0;
156
+ }
157
+
158
+
153
159
  buildFilterQuery(qb: SelectQueryBuilder<any>, basicFilterDto: BasicFilterDto, entityAlias: string): SelectQueryBuilder<any> { //TODO : Check how to pass a type to SelectQueryBuilder instead of any
154
160
  let { limit, offset, showSoftDeleted, filters } = basicFilterDto;
155
161
  const { fields, sort, groupBy, populate = [] } = basicFilterDto;
@@ -163,6 +169,11 @@ export class CrudHelperService {
163
169
  throw new Error('buildFilterQuery: Only 1 Group by field is supported currently');
164
170
  }
165
171
 
172
+ // Depending upon the populate option, apply the join clause
173
+ if (normalizedPopulate && normalizedPopulate.length) {
174
+ this.buildPopulateQuery(normalizedPopulate, entityAlias, qb);
175
+ }
176
+
166
177
  if (filters) {
167
178
  qb.where(new Brackets(whereQb => {
168
179
  this.applyFilters(whereQb, filters, entityAlias, qb);
@@ -177,15 +188,6 @@ export class CrudHelperService {
177
188
  }));
178
189
  }
179
190
 
180
- // Depending upon the populate option, apply the join clause
181
- if (normalizedPopulate && normalizedPopulate.length) {
182
- normalizedPopulate.forEach((relation) => {
183
- // Check if the relation is already joined, if not then join it
184
- const joinProperty = `${entityAlias}.${relation}`;
185
- if (!this.isRelationJoined(qb, joinProperty)) qb.leftJoinAndSelect(joinProperty, relation);
186
- });
187
- }
188
-
189
191
  // Depending upon the order option, apply the order by clause
190
192
  if (normalizedSort && normalizedSort.length) {
191
193
  const orderOptions = this.orderOptions(normalizedSort);
@@ -214,9 +216,33 @@ export class CrudHelperService {
214
216
  qb.addGroupBy(`${entityAlias}.${field}`);
215
217
  });
216
218
  }
217
- // Apply the pagination options
218
- if (limit) qb.limit(limit);
219
- if (offset) qb.offset(offset);
219
+
220
+ // Apply the pagination options & handle the case when the query has joins
221
+ if (limit) this.hasJoins(qb) ? qb.take(limit) : qb.limit(limit);
222
+ if (offset) this.hasJoins(qb) ? qb.skip(offset): qb.offset(offset);
223
+ return qb;
224
+ }
225
+
226
+ private buildPopulateQuery(normalizedPopulate: string[], entityAlias: string, qb: SelectQueryBuilder<any>) {
227
+ normalizedPopulate.forEach((relation) => {
228
+ this.buildJoinQueryForRelation(qb, entityAlias, relation);
229
+ });
230
+ return qb;
231
+ }
232
+
233
+ private buildJoinQueryForRelation(qb: SelectQueryBuilder<any>, entityAlias: string, relation: string) {
234
+ // We split the joinProperty to get the alias of the entity we are joining
235
+ const relationParts = relation.split('.');
236
+ let parentAlias = entityAlias;
237
+ relationParts.forEach((part, i) => {
238
+ const joinProperty = `${parentAlias}.${part}`;
239
+ // Check if the relation is already joined, if not then join it
240
+ if (!this.isRelationJoined(qb, joinProperty)) {
241
+ const joinAlias = relationParts.slice(0, i + 1).join('_');
242
+ qb.leftJoinAndSelect(joinProperty, joinAlias);
243
+ }
244
+ parentAlias = part; // Update the parent alias for the next iteration
245
+ });
220
246
  return qb;
221
247
  }
222
248
 
@@ -99,20 +99,6 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
99
99
  }
100
100
  }
101
101
 
102
- private async loadInverseRelationFields() {
103
- const fieldMetadataRepo = this.entityManager.getRepository(FieldMetadata);
104
- // Since the fields in the dto could be a result of being on a inverse side of a relation, we need to get the field configuration from the inverse side to process it
105
- const inverseRelationFields = await fieldMetadataRepo.find({
106
- where: {
107
- type: 'relation',
108
- relationCoModelSingularName: this.modelName,
109
- relationCreateInverse: true,
110
- },
111
- relations: ['model'],
112
- });
113
- return inverseRelationFields;
114
- }
115
-
116
102
  private async loadModel() {
117
103
  return await this.modelMetadataService.findOneBySingularName(this.modelName, {
118
104
  fields: {
@@ -414,28 +400,22 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
414
400
  const alias = 'entity';
415
401
  // Extract the required keys from the input query
416
402
  let { limit, offset, populateMedia, populateGroup, groupFilter } = basicFilterDto;
417
- const model = await this.loadModel();
403
+ const {singularName} = await this.loadModel();
418
404
  // Check wheather user has update permission for model
419
405
  if (solidRequestContext.activeUser) {
420
- const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, model.singularName);
406
+ const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, singularName);
421
407
  if (!hasPermission) {
422
408
  throw new BadRequestException('Forbidden');
423
409
  }
424
410
  }
425
411
 
426
- // Exclude one-to-many and many-to-one relations from the initial filter query, since they will be queried separately
427
- const relationsExcludedFromInitialQuery = this.relationsExcludedFromInitialQuery(model, basicFilterDto.populate);
428
- basicFilterDto = this.getRevisedFilterDto(basicFilterDto, relationsExcludedFromInitialQuery);
429
-
430
412
  // Create above query on pincode table using query builder
431
413
  var qb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias)
432
414
  qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);
433
415
 
434
416
  if (basicFilterDto.groupBy) {
435
- const relationsExcludedFromInitialQuery = this.relationsExcludedFromInitialQuery(model, groupFilter.populate);
436
- groupFilter = this.getRevisedFilterDto(groupFilter, relationsExcludedFromInitialQuery);
437
417
  // Get the records and the count
438
- const { groupMeta, groupRecords } = await this.handleGroupFind(qb, groupFilter, populateGroup, alias, populateMedia, relationsExcludedFromInitialQuery);
418
+ const { groupMeta, groupRecords } = await this.handleGroupFind(qb, groupFilter, populateGroup, alias, populateMedia);
439
419
  return {
440
420
  groupMeta,
441
421
  groupRecords,
@@ -443,7 +423,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
443
423
  }
444
424
  else {
445
425
  // Get the records and the count
446
- const { meta, records } = await this.handleNonGroupFind(qb, populateMedia, offset, limit, alias, relationsExcludedFromInitialQuery);
426
+ const { meta, records } = await this.handleNonGroupFind(qb, populateMedia, offset, limit, alias);
447
427
  return {
448
428
  meta,
449
429
  records,
@@ -451,28 +431,9 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
451
431
  }
452
432
  }
453
433
 
454
- private getRevisedFilterDto(basicFilterDto: BasicFilterDto, relationsExcludedFromInitialQuery: string[]): BasicFilterDto {
455
- const normalizedPopulate = this.crudHelperService.normalize(basicFilterDto.populate);
456
- if (normalizedPopulate.length === 0 || relationsExcludedFromInitialQuery.length === 0) return basicFilterDto;
457
- return { ...basicFilterDto, populate: normalizedPopulate.filter(populate => !relationsExcludedFromInitialQuery.includes(populate)) };
458
- }
459
-
460
- private relationsExcludedFromInitialQuery(model: ModelMetadata, relationsToBePopulated: string[] = []): string[] {
461
- const relationToBeExcluded =
462
- model.fields
463
- .filter(field => field.type === 'relation' && [RelationType.manyTomany, RelationType.oneToMany].includes(field.relationType as RelationType))
464
- .map(field => field.name);
465
- return relationsToBePopulated.filter(relation => relationToBeExcluded.includes(relation));
466
- }
467
-
468
- private async handleNonGroupFind(qb: SelectQueryBuilder<T>, populateMedia: string[], offset: number, limit: number, alias: string, relationsExcludedFromInitialQuery: string[]) {
434
+ private async handleNonGroupFind(qb: SelectQueryBuilder<T>, populateMedia: string[], offset: number, limit: number, alias: string) {
469
435
  const [entities, count] = await qb.getManyAndCount();
470
436
 
471
- // Populate the excluded relations for the entities
472
- if (relationsExcludedFromInitialQuery.length > 0) {
473
- await this.populateExcludedRelations(entities, relationsExcludedFromInitialQuery, alias);
474
- }
475
-
476
437
  // Populate the entity with the media
477
438
  if (populateMedia && populateMedia.length > 0) {
478
439
  await this.handlePopulateMedia(populateMedia, entities);
@@ -481,36 +442,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
481
442
  return this.wrapFindResponse(offset, limit, count, entities);
482
443
  }
483
444
 
484
- private async populateExcludedRelations(entities: T[], relationsExcludedFromInitialQuery: string[], alias: string) {
485
- //@ts-ignore
486
- const ids = entities.map(entity => entity.id);
487
-
488
- // Fire a query to get the records from the relation entity which match the ids
489
- // Create a map with key as the entity id and value as the qb records
490
- const relationEntitiesMap = {};
491
- for (const relation of relationsExcludedFromInitialQuery) {
492
- const qb = this.repo.createQueryBuilder(`${alias}`)
493
- .leftJoinAndSelect(`${alias}.${relation}`, relation)
494
- .where(`${alias}.id IN (:...ids)`, { ids })
495
- // .limit(DEFAULT_LIMIT)
496
- // .offset(DEFAULT_OFFSET);
497
- const relationEntities = await qb.getMany();
498
- relationEntitiesMap[relation] = relationEntities;
499
- }
500
-
501
- // Iterate over the map and assign the relation entities to the entity
502
- for (const relation of relationsExcludedFromInitialQuery) {
503
- for (const entity of entities) {
504
- const entityRelations = relationEntitiesMap[relation]
505
- //@ts-ignore
506
- .filter((joinedEntity: T) => joinedEntity.id === entity.id)
507
- .flatMap((joinedEntity: T) => joinedEntity[relation]);
508
- entity[relation] = entityRelations;
509
- }
510
- }
511
- }
512
-
513
- private async handleGroupFind(qb: SelectQueryBuilder<T>, groupFilter: BasicFilterDto, populateGroup: boolean, alias: string, populateMedia: string[], relationsExcludedFromInitialQuery: string[]) {
445
+ private async handleGroupFind(qb: SelectQueryBuilder<T>, groupFilter: BasicFilterDto, populateGroup: boolean, alias: string, populateMedia: string[]) {
514
446
  const groupByResult = await qb.getRawMany();
515
447
 
516
448
  const groupMeta = [];
@@ -523,11 +455,6 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
523
455
  groupByQb = this.crudHelperService.buildGroupByRecordsQuery(groupByQb, group, alias);
524
456
  const [entities, count] = await groupByQb.getManyAndCount();
525
457
 
526
- // Populate the excluded relations for the entities
527
- if (relationsExcludedFromInitialQuery.length > 0) {
528
- await this.populateExcludedRelations(entities, relationsExcludedFromInitialQuery, alias);
529
- }
530
-
531
458
  // Populate the entity with the media
532
459
  if (populateMedia && populateMedia.length > 0) {
533
460
  await this.handlePopulateMedia(populateMedia, entities);
@@ -308,7 +308,7 @@ export class FieldMetadataService {
308
308
  // return this.moduleMetadataRepo.save(country);
309
309
  // }
310
310
 
311
- async remove(id: number) {
311
+ async delete(id: number) {
312
312
  const entity = await this.findOne(id);
313
313
  return this.fieldMetadataRepo.remove(entity);
314
314
  }
@@ -855,9 +855,7 @@ export class FieldMetadataService {
855
855
  "encrypt",
856
856
  "encryptionType",
857
857
  "decryptWhen",
858
- "columnName",
859
- "isUserKey"
860
-
858
+ "columnName"
861
859
  ];
862
860
 
863
861
  case SolidFieldType.selectionDynamic:
@@ -145,7 +145,7 @@ export class MediaStorageProviderMetadataService {
145
145
  return removedEntities
146
146
  }
147
147
 
148
- async remove(id: number) {
148
+ async delete(id: number) {
149
149
  const lov = await this.findOne(id);
150
150
  return this.mediaStorageProviderRepo.remove(lov);
151
151
  }
@@ -622,8 +622,8 @@ export class ModelMetadataService {
622
622
  dataSourceType: model.dataSourceType,
623
623
  tableName: model.tableName,
624
624
  userKeyFieldUserKey: model.fields.find(field => field.isUserKey)?.name,
625
- isChild: model.isChild,
626
- parentModelUserKey: model.parentModel.singularName,
625
+ isChild: model?.isChild,
626
+ parentModelUserKey: model?.parentModel?.singularName,
627
627
  fields: []
628
628
  }
629
629
 
@@ -897,7 +897,7 @@ export class ModelMetadataService {
897
897
  // Remove the fields from the database as well. This also checks, if the field is marked for removal
898
898
  fieldsForRemoval.forEach((field: FieldMetadata) => {
899
899
  if (field.isMarkedForRemoval) {
900
- this.fieldMetadataService.remove(field.id);
900
+ this.fieldMetadataService.delete(field.id);
901
901
  }
902
902
  });
903
903
  return removeOutput;
@@ -909,7 +909,7 @@ export class ModelMetadataService {
909
909
  }
910
910
 
911
911
  const query = {
912
- populate: ["module", "fields", "parentModel"]
912
+ populate: ["module", "fields", "parentModel", "parentModel.module"]
913
913
  };
914
914
  const model = options.modelId ? await this.findOne(options.modelId, query) : await this.findOneByUserKey(options.modelUserKey, query.populate);
915
915
 
@@ -932,7 +932,9 @@ export class ModelMetadataService {
932
932
  table: model.tableName,
933
933
  fields: fieldsForRefresh,
934
934
  modelEnableSoftDelete: model.enableSoftDelete,
935
- parentModel: model.parentModel?.singularName
935
+ parentModel: model.parentModel?.singularName,
936
+ parentModule: model.parentModel?.module?.name,
937
+
936
938
  },
937
939
  dryRun
938
940
  );