@solidstarters/solid-core 1.2.138 → 1.2.139

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.
@@ -4,9 +4,9 @@ export interface ManyToOneRelationFieldOptions {
4
4
  required: boolean | undefined | null;
5
5
  relationCoModelSingularName: string | undefined | null;
6
6
  fieldName: string | undefined | null;
7
- modelUserKeyFieldName: string | undefined | null;
8
7
  modelSingularName: string | undefined | null;
9
8
  entityManager: EntityManager;
9
+ relationCoModelUserKeyFieldName: string | undefined | null;
10
10
  }
11
11
  export declare class ManyToOneRelationFieldCrudManager implements FieldCrudManager {
12
12
  private readonly options;
@@ -1 +1 @@
1
- {"version":3,"file":"ManyToOneRelationFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,6BAA6B;IAE1C,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,2BAA2B,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACvD,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,qBAAqB,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACjD,iBAAiB,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC7C,aAAa,EAAE,aAAa,CAAC;CAChC;AAGD,qBAAa,iCAAkC,YAAW,gBAAgB;IAG1D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAS;gBACJ,OAAO,EAAE,6BAA6B;IAKnE,QAAQ,CAAC,GAAG,EAAE,GAAG;IAMjB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,6BAA6B;IAS/B,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IA0BhD,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,sBAAsB;CAMjC"}
1
+ {"version":3,"file":"ManyToOneRelationFieldCrudManager.d.ts","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,6BAA6B;IAE1C,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrC,2BAA2B,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACvD,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAErC,iBAAiB,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC7C,aAAa,EAAE,aAAa,CAAC;IAC7B,+BAA+B,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;CAC9D;AAGD,qBAAa,iCAAkC,YAAW,gBAAgB;IAG1D,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,gBAAgB,CAAS;gBACJ,OAAO,EAAE,6BAA6B;IAKnE,QAAQ,CAAC,GAAG,EAAE,GAAG;IAMjB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,6BAA6B;IAS/B,kBAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IA0BhD,OAAO,CAAC,yBAAyB;IAKjC,OAAO,CAAC,sBAAsB;CAMjC"}
@@ -34,8 +34,8 @@ class ManyToOneRelationFieldCrudManager {
34
34
  applyUserKeyFormatValidations(fieldUserKey) {
35
35
  const errors = [];
36
36
  !(0, class_validator_1.isString)(fieldUserKey) ? errors.push({ field: this.options.fieldName, error: 'Field is not a string' }) : "no errors";
37
- if ((0, class_validator_1.isEmpty)(this.options.modelUserKeyFieldName)) {
38
- errors.push({ field: this.options.fieldName, error: `UserKey field name is not defined in the model ${this.options.modelSingularName}` });
37
+ if ((0, class_validator_1.isEmpty)(this.options.relationCoModelUserKeyFieldName)) {
38
+ errors.push({ field: this.options.fieldName, error: `UserKey field name is not defined in the model ${this.options.relationCoModelSingularName}` });
39
39
  }
40
40
  return errors;
41
41
  }
@@ -52,9 +52,9 @@ class ManyToOneRelationFieldCrudManager {
52
52
  }
53
53
  }
54
54
  else {
55
- dto[this.options.fieldName] = await this.options.entityManager.getRepository(entityTarget).findOneBy({ [this.options.modelUserKeyFieldName]: fieldUserKeyValue });
55
+ dto[this.options.fieldName] = await this.options.entityManager.getRepository(entityTarget).findOneBy({ [this.options.relationCoModelUserKeyFieldName]: fieldUserKeyValue });
56
56
  if (this.options.required && (0, class_validator_1.isEmpty)(dto[this.options.fieldName])) {
57
- throw new Error(`ManyToOneRelationFieldCrudManager: Record with userKey: ${this.options.modelUserKeyFieldName}: ${fieldUserKeyValue} not found in ${this.options.relationCoModelSingularName}`);
57
+ throw new Error(`ManyToOneRelationFieldCrudManager: Record with userKey: ${this.options.relationCoModelUserKeyFieldName}: ${fieldUserKeyValue} not found in ${this.options.relationCoModelSingularName}`);
58
58
  }
59
59
  }
60
60
  return dto;
@@ -1 +1 @@
1
- {"version":3,"file":"ManyToOneRelationFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { classify } from \"@angular-devkit/core/src/utils/strings\";\nimport { isEmpty, isNotEmpty, isString } from \"class-validator\";\nimport { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { IsParsableInt } from \"src/validators/is-parsable-int\";\nimport { EntityManager } from \"typeorm\";\n\nexport interface ManyToOneRelationFieldOptions {\n // Add options for relation field\n required: boolean | undefined | null;\n relationCoModelSingularName: string | undefined | null;\n fieldName: string | undefined | null;\n modelUserKeyFieldName: string | undefined | null;\n modelSingularName: string | undefined | null;\n entityManager: EntityManager;\n}\n\n// This implementation is meant to be used for many-to-one relation field\nexport class ManyToOneRelationFieldCrudManager implements FieldCrudManager {\n private idFieldName: string;\n private userKeyFieldName: string;\n constructor(private readonly options: ManyToOneRelationFieldOptions) {\n // this.options = options;\n this.idFieldName = `${options.fieldName}Id`;\n this.userKeyFieldName = `${options.fieldName}UserKey`;\n }\n validate(dto: any) {\n const fieldId: number = dto[this.idFieldName];\n const fieldUserKey: string = dto[this.userKeyFieldName];\n return this.applyValidations(fieldId, fieldUserKey);\n }\n\n private applyValidations(fieldId: any, fieldUserKey: string): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyRequiredValidation() && isEmpty(fieldId) && isEmpty(fieldUserKey) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required. Either pass ${this.idFieldName} or ${this.userKeyFieldName}.` }) : \"no errors\";\n if (isNotEmpty(fieldId)) {\n errors.push(...this.applyIdFormatValidations(fieldId));\n }\n if (isNotEmpty(fieldUserKey)) {\n errors.push(...this.applyUserKeyFormatValidations(fieldUserKey));\n }\n return errors;\n }\n\n private applyIdFormatValidations(fieldId: any): ValidationError[] { //FIXME fieldId is any because it can be string or number. Keeping it any for compatibility with isParsableInt. \n const errors: ValidationError[] = [];\n !IsParsableInt(fieldId) ? errors.push({ field: this.options.fieldName, error: 'Field is not a integer' }) : \"no errors\";\n return errors;\n }\n\n private applyUserKeyFormatValidations(fieldUserKey: string): ValidationError[] {\n const errors: ValidationError[] = [];\n !isString(fieldUserKey) ? errors.push({ field: this.options.fieldName, error: 'Field is not a string' }) : \"no errors\";\n if (isEmpty(this.options.modelUserKeyFieldName)) {\n errors.push({ field: this.options.fieldName, error: `UserKey field name is not defined in the model ${this.options.modelSingularName}` });\n }\n return errors;\n }\n\n async transformForCreate(dto: any): Promise<any> {\n const fieldId: number = dto[this.idFieldName];\n const fieldUserKeyValue: string = dto[this.userKeyFieldName];\n\n // Avoid transforming if both fieldId and fieldUserKey is empty\n if ((isEmpty(fieldId)) && isEmpty(fieldUserKeyValue)) return dto;\n\n // // Load the related entity from the database, using the repository of the related entity\n const entityTarget = this.getRelatedEntityTarget(classify(this.options.relationCoModelSingularName));\n if (isNotEmpty(fieldId)) {\n dto[this.options.fieldName] = await this.options.entityManager.getRepository(entityTarget).findOneBy({ id: fieldId });\n if (this.options.required && isEmpty(dto[this.options.fieldName])) {\n throw new Error(`ManyToOneRelationFieldCrudManager: Record with id: ${fieldId} not found in ${this.options.relationCoModelSingularName}`);\n }\n }\n else {\n dto[this.options.fieldName] = await this.options.entityManager.getRepository(entityTarget).findOneBy({ [this.options.modelUserKeyFieldName]: fieldUserKeyValue });\n if (this.options.required && isEmpty(dto[this.options.fieldName])) {\n throw new Error(`ManyToOneRelationFieldCrudManager: Record with userKey: ${this.options.modelUserKeyFieldName}: ${fieldUserKeyValue} not found in ${this.options.relationCoModelSingularName}`);\n }\n }\n\n\n return dto;\n }\n\n private isApplyRequiredValidation(): boolean {\n return this.options.required;\n }\n\n // Returns the entity target class from the entity name\n private getRelatedEntityTarget(relatedEntityName: string): any {\n const entityMetadatas = this.options.entityManager.connection.entityMetadatas;\n const relatedEntityMetadata = entityMetadatas.find(em => em.name === relatedEntityName);\n return relatedEntityMetadata.target;\n }\n\n}"]}
1
+ {"version":3,"file":"ManyToOneRelationFieldCrudManager.js","sourceRoot":"","sources":["../../../src/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { classify } from \"@angular-devkit/core/src/utils/strings\";\nimport { isEmpty, isNotEmpty, isString } from \"class-validator\";\nimport { FieldCrudManager, ValidationError } from \"src/interfaces\";\nimport { IsParsableInt } from \"src/validators/is-parsable-int\";\nimport { EntityManager } from \"typeorm\";\n\nexport interface ManyToOneRelationFieldOptions {\n // Add options for relation field\n required: boolean | undefined | null;\n relationCoModelSingularName: string | undefined | null;\n fieldName: string | undefined | null;\n // modelUserKeyFieldName: string | undefined | null;\n modelSingularName: string | undefined | null;\n entityManager: EntityManager;\n relationCoModelUserKeyFieldName: string | undefined | null; \n}\n\n// This implementation is meant to be used for many-to-one relation field\nexport class ManyToOneRelationFieldCrudManager implements FieldCrudManager {\n private idFieldName: string;\n private userKeyFieldName: string;\n constructor(private readonly options: ManyToOneRelationFieldOptions) {\n // this.options = options;\n this.idFieldName = `${options.fieldName}Id`;\n this.userKeyFieldName = `${options.fieldName}UserKey`;\n }\n validate(dto: any) {\n const fieldId: number = dto[this.idFieldName];\n const fieldUserKey: string = dto[this.userKeyFieldName];\n return this.applyValidations(fieldId, fieldUserKey);\n }\n\n private applyValidations(fieldId: any, fieldUserKey: string): ValidationError[] {\n const errors: ValidationError[] = [];\n this.isApplyRequiredValidation() && isEmpty(fieldId) && isEmpty(fieldUserKey) ? errors.push({ field: this.options.fieldName, error: `Field: ${this.options.fieldName} is required. Either pass ${this.idFieldName} or ${this.userKeyFieldName}.` }) : \"no errors\";\n if (isNotEmpty(fieldId)) {\n errors.push(...this.applyIdFormatValidations(fieldId));\n }\n if (isNotEmpty(fieldUserKey)) {\n errors.push(...this.applyUserKeyFormatValidations(fieldUserKey));\n }\n return errors;\n }\n\n private applyIdFormatValidations(fieldId: any): ValidationError[] { //FIXME fieldId is any because it can be string or number. Keeping it any for compatibility with isParsableInt. \n const errors: ValidationError[] = [];\n !IsParsableInt(fieldId) ? errors.push({ field: this.options.fieldName, error: 'Field is not a integer' }) : \"no errors\";\n return errors;\n }\n\n private applyUserKeyFormatValidations(fieldUserKey: string): ValidationError[] {\n const errors: ValidationError[] = [];\n !isString(fieldUserKey) ? errors.push({ field: this.options.fieldName, error: 'Field is not a string' }) : \"no errors\";\n if (isEmpty(this.options.relationCoModelUserKeyFieldName)) {\n errors.push({ field: this.options.fieldName, error: `UserKey field name is not defined in the model ${this.options.relationCoModelSingularName}` });\n }\n return errors;\n }\n\n async transformForCreate(dto: any): Promise<any> {\n const fieldId: number = dto[this.idFieldName];\n const fieldUserKeyValue: string = dto[this.userKeyFieldName];\n\n // Avoid transforming if both fieldId and fieldUserKey is empty\n if ((isEmpty(fieldId)) && isEmpty(fieldUserKeyValue)) return dto;\n\n // // Load the related entity from the database, using the repository of the related entity\n const entityTarget = this.getRelatedEntityTarget(classify(this.options.relationCoModelSingularName));\n if (isNotEmpty(fieldId)) {\n dto[this.options.fieldName] = await this.options.entityManager.getRepository(entityTarget).findOneBy({ id: fieldId });\n if (this.options.required && isEmpty(dto[this.options.fieldName])) {\n throw new Error(`ManyToOneRelationFieldCrudManager: Record with id: ${fieldId} not found in ${this.options.relationCoModelSingularName}`);\n }\n }\n else {\n dto[this.options.fieldName] = await this.options.entityManager.getRepository(entityTarget).findOneBy({ [this.options.relationCoModelUserKeyFieldName]: fieldUserKeyValue });\n if (this.options.required && isEmpty(dto[this.options.fieldName])) {\n throw new Error(`ManyToOneRelationFieldCrudManager: Record with userKey: ${this.options.relationCoModelUserKeyFieldName}: ${fieldUserKeyValue} not found in ${this.options.relationCoModelSingularName}`);\n }\n }\n\n\n return dto;\n }\n\n private isApplyRequiredValidation(): boolean {\n return this.options.required;\n }\n\n // Returns the entity target class from the entity name\n private getRelatedEntityTarget(relatedEntityName: string): any {\n const entityMetadatas = this.options.entityManager.connection.entityMetadatas;\n const relatedEntityMetadata = entityMetadatas.find(em => em.name === relatedEntityName);\n return relatedEntityMetadata.target;\n }\n\n}"]}
@@ -70,5 +70,6 @@ export declare class CRUDService<T> {
70
70
  recoveredIds: number[];
71
71
  }>;
72
72
  getFieldMetadataRecursively(pathParts: string[], fields: FieldMetadata[]): any;
73
+ getUserKeyFieldNameForModel(modelSingularName: string): Promise<string>;
73
74
  }
74
75
  //# sourceMappingURL=crud.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"crud.service.d.ts","sourceRoot":"","sources":["../../src/services/crud.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crud.service.d.ts","sourceRoot":"","sources":["../../src/services/crud.service.ts"],"names":[],"mappings":"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"}
@@ -84,7 +84,7 @@ class CRUDService {
84
84
  });
85
85
  }
86
86
  async validateAndTransformDto(field, dto, files, hasMediaFields, isPartialUpdate = false, isUpdate = false) {
87
- const fieldManager = this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate);
87
+ const fieldManager = await this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate);
88
88
  const validationErrors = fieldManager.validate(dto, files);
89
89
  const errors = (validationErrors instanceof Promise) ? await validationErrors : validationErrors;
90
90
  if (errors.length > 0) {
@@ -189,7 +189,7 @@ class CRUDService {
189
189
  return this.repo.remove(entity);
190
190
  }
191
191
  }
192
- fieldCrudManager(fieldMetadata, entityManager, isPartialUpdate = false, isUpdate = false) {
192
+ async fieldCrudManager(fieldMetadata, entityManager, isPartialUpdate = false, isUpdate = false) {
193
193
  const commonOptions = { required: fieldMetadata.required && !isPartialUpdate, fieldName: fieldMetadata.name, isUpdate };
194
194
  switch (fieldMetadata.type) {
195
195
  case create_field_metadata_dto_1.SolidFieldType.shortText: {
@@ -244,11 +244,12 @@ class CRUDService {
244
244
  }
245
245
  case create_field_metadata_dto_1.SolidFieldType.relation: {
246
246
  if (fieldMetadata.relationType === create_field_metadata_dto_1.RelationType.manyToOne) {
247
+ const relationCoModelUserKeyFieldName = await this.getUserKeyFieldNameForModel(fieldMetadata.relationCoModelSingularName);
247
248
  const manyToOneOptions = {
248
249
  ...commonOptions,
249
250
  relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,
250
- modelUserKeyFieldName: fieldMetadata.model.userKeyField?.name,
251
251
  modelSingularName: fieldMetadata.model.singularName,
252
+ relationCoModelUserKeyFieldName: relationCoModelUserKeyFieldName,
252
253
  entityManager,
253
254
  };
254
255
  return new ManyToOneRelationFieldCrudManager_1.ManyToOneRelationFieldCrudManager(manyToOneOptions);
@@ -517,7 +518,7 @@ class CRUDService {
517
518
  const files = [];
518
519
  let hasMediaFields = false;
519
520
  for (const field of model.fields) {
520
- const fieldManager = this.fieldCrudManager(field, this.entityManager);
521
+ const fieldManager = await this.fieldCrudManager(field, this.entityManager);
521
522
  const validationErrors = await fieldManager.validate(createDto, files);
522
523
  if (validationErrors.length > 0) {
523
524
  throw new common_1.BadRequestException(`Validation errors in ${field.name} are invalid: ${validationErrors.map(e => e.error).join(', ')}`);
@@ -658,6 +659,13 @@ class CRUDService {
658
659
  }
659
660
  return this.getFieldMetadataRecursively(remainingParts, relationCoModel.fields);
660
661
  }
662
+ async getUserKeyFieldNameForModel(modelSingularName) {
663
+ const model = await this.modelMetadataService.findOneBySingularName(modelSingularName, ['userKeyField']);
664
+ if (!model) {
665
+ throw new common_1.BadRequestException(`Model ${modelSingularName} not found`);
666
+ }
667
+ return model.userKeyField?.name || '';
668
+ }
661
669
  }
662
670
  exports.CRUDService = CRUDService;
663
671
  //# sourceMappingURL=crud.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"crud.service.js","sourceRoot":"","sources":["../../src/services/crud.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BadRequestException, Inject, Optional } from \"@nestjs/common\";\nimport { ConfigService, ConfigType } from \"@nestjs/config\";\nimport { DiscoveryService, ModuleRef } from \"@nestjs/core\";\nimport { EntityManager, In, IsNull, Not, QueryFailedError, SelectQueryBuilder } from \"typeorm\";\nimport { Repository } from \"typeorm/repository/Repository\";\nimport { BasicFilterDto } from \"../dtos/basic-filters.dto\";\nimport { ComputedFieldValueType, RelationType, SelectionValueType, SolidFieldType } from \"../dtos/create-field-metadata.dto\";\nimport { MediaStorageProviderType } from \"../dtos/create-media-storage-provider-metadata.dto\";\nimport { FieldMetadata } from \"../entities/field-metadata.entity\";\nimport { ModelMetadata } from \"../entities/model-metadata.entity\";\nimport { BigIntFieldCrudManager } from \"../helpers/field-crud-managers/BigIntFieldCrudManager\";\nimport { BooleanFieldCrudManager } from \"../helpers/field-crud-managers/BooleanFieldCrudManager\";\nimport { ComputedFieldCrudManager } from \"../helpers/field-crud-managers/ComputedFieldCrudManager\";\nimport { DateFieldCrudManager } from \"../helpers/field-crud-managers/DateFieldCrudManager\";\nimport { DecimalFieldCrudManager } from \"../helpers/field-crud-managers/DecimalFieldCrudManager\";\nimport { EmailFieldCrudManager, MAX_EMAIL_LENGTH } from \"../helpers/field-crud-managers/EmailFieldCrudManager\";\nimport { IntFieldCrudManager } from \"../helpers/field-crud-managers/IntFieldCrudManager\";\nimport { JsonFieldCrudManager } from \"../helpers/field-crud-managers/JsonFieldCrudManager\";\nimport { LongTextFieldCrudManager } from \"../helpers/field-crud-managers/LongTextFieldCrudManager\";\nimport { ManyToManyRelationFieldCrudManager, ManyToManyRelationFieldOptions } from \"../helpers/field-crud-managers/ManyToManyRelationFieldCrudManager\";\nimport { ManyToOneRelationFieldCrudManager, ManyToOneRelationFieldOptions } from \"../helpers/field-crud-managers/ManyToOneRelationFieldCrudManager\";\nimport { MediaFieldCrudManager, SolidMediaType } from \"../helpers/field-crud-managers/MediaFieldCrudManager\";\nimport { NoOpsFieldCrudManager } from \"../helpers/field-crud-managers/NoOpsFieldCrudManager\";\nimport { OneToManyRelationFieldCrudManager, OneToManyRelationFieldOptions } from \"../helpers/field-crud-managers/OneToManyRelationFieldCrudManager\";\nimport { PasswordFieldCrudManager } from \"../helpers/field-crud-managers/PasswordFieldCrudManager\";\nimport { RichTextFieldCrudManager } from \"../helpers/field-crud-managers/RichTextFieldCrudManager\";\nimport { SelectionDynamicFieldCrudManager } from \"../helpers/field-crud-managers/SelectionDynamicFieldCrudManager\";\nimport { SelectionStaticFieldCrudManager } from \"../helpers/field-crud-managers/SelectionStaticFieldCrudManager\";\nimport { ShortTextFieldCrudManager } from \"../helpers/field-crud-managers/ShortTextFieldCrudManager\";\nimport { UUIDFieldCrudManager } from \"../helpers/field-crud-managers/UUIDFieldCrudManager\";\nimport { FieldCrudManager, MediaWithFullUrl } from \"../interfaces\";\nimport { CrudHelperService } from \"./crud-helper.service\";\nimport { FileService } from \"./file.service\";\nimport { getMediaStorageProvider } from \"./mediaStorageProviders\";\nimport { ModelMetadataService } from \"./model-metadata.service\";\nimport { ModuleMetadataService } from \"./module-metadata.service\";\nimport { isArray } from \"class-validator\";\n\nexport class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDto, so we get the proper types in our service\n\n constructor(\n readonly modelMetadataService: ModelMetadataService,\n readonly moduleMetadataService: ModuleMetadataService,\n readonly configService: ConfigService,\n readonly fileService: FileService,\n readonly discoveryService: DiscoveryService,\n readonly crudHelperService: CrudHelperService,\n readonly entityManager: EntityManager,\n readonly repo: Repository<T>,\n readonly modelName: string,\n readonly moduleName: string,\n readonly moduleRef: ModuleRef,\n //We can just have the Model Entity here\n ) { }\n\n async create(createDto: any, files: Express.Multer.File[] = [], solidRequestContext: any = {}): Promise<T> {\n // This class will be extended by the generated service class i.e PersonService\n // The data required to identify the model and module name will be passed from the generate CrudService subclass\n //TODO: Algorithm to create the entity\n // 1. Fire a query and load all the fields in the provided model name for a particular module\n // FIXME This can be optimized to take in module name i.e (handle scenario wherein same model exists in multiple modules)\n let hasMediaFields = false;\n\n const model = await this.loadModel();\n // Check wheather user has create permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, model.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n // const inverseRelationFields = await this.loadInverseRelationFields();\n const fieldsToProcess = [...model.fields];\n\n // 2. Loop through the fields with a switch statement\n // 3. Handle the fields based on field type\n for (const field of fieldsToProcess) {\n const transformed = await this.validateAndTransformDto(field, createDto, files, hasMediaFields);\n createDto = transformed.dto;\n hasMediaFields = transformed.hasMediaFields;\n };\n try {\n // 5. Save the entity\n // For media, we need to use a storage provider and save the media, then save the associated uri against the entity or media table\n const entity = this.repo.create(createDto);\n const savedEntity = await this.repo.save(entity) as T;\n\n // 6. Save the media\n if (hasMediaFields) {\n this.saveMedia(model, files, savedEntity);\n }\n return savedEntity;\n } catch (error) {\n if (error instanceof QueryFailedError && error.message.includes('duplicate key value violates unique constraint')) {\n throw new BadRequestException('Duplicate entry. A record with similar unique fields already exists.');\n }\n throw error;\n }\n }\n\n private async loadModel() {\n return await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: {\n userKeyField: true\n },\n mediaStorageProvider: true,\n },\n module: true,\n });\n }\n\n private async validateAndTransformDto(field: FieldMetadata, dto: any, files: Express.Multer.File[], hasMediaFields: boolean, isPartialUpdate: boolean = false, isUpdate: boolean = false) {\n const fieldManager: FieldCrudManager = this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate);\n const validationErrors = fieldManager.validate(dto, files);\n const errors = (validationErrors instanceof Promise) ? await validationErrors : validationErrors;\n if (errors.length > 0) {\n throw new BadRequestException(`Validation errors in ${field.name} is invalid i.e ${errors.map(e => e.error).join(', ')}`); //FIXME: Better to return a validation error object\n }\n const dtoOrPromise = fieldManager.transformForCreate(dto);\n dto = (dtoOrPromise instanceof Promise) ? await dtoOrPromise : dtoOrPromise;\n hasMediaFields = hasMediaFields || field.type === 'mediaSingle' || field.type === 'mediaMultiple';\n return { dto, hasMediaFields };\n }\n\n //FIXME: Need to make this saving media async. Use queues approach\n private saveMedia(model: ModelMetadata, files: Express.Multer.File[], savedEntity: T) {\n // Get all the media fields in the dto\n\n const mediaFields = model.fields.filter(field => field.type === 'mediaSingle' || field.type === 'mediaMultiple');\n\n // Depending upon media storage provider configured, get the appropriate storage provider\n mediaFields.forEach(async (mediaField) => {\n const media = files.filter(multerFile => multerFile.fieldname === mediaField.name);\n\n // If media is present, then save the media\n if (media.length > 0) {\n const storageProviderMetadata = mediaField.mediaStorageProvider;\n\n // Use the storage provider metadata to get the appropriate storage provider implementation\n const storageProviderType = storageProviderMetadata.type as MediaStorageProviderType;\n\n // Get the storage provider implementation\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n\n //Commented the below code since we will be direclty images from server on call from ui \n // await storageProvider.delete(savedEntity, mediaField);\n await storageProvider.store(media, savedEntity, mediaField);\n }\n });\n }\n\n //TODO: Will the updates be partial i.e PATCH or full i.e PUT\n async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}, isUpdate: boolean = false): Promise<T> {\n if (!id) {\n throw new Error('Id is required for update');\n }\n isUpdate = true;\n const model = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasUpdatePermissionOnModel(solidRequestContext.activeUser, model.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n const entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n if (!entity) {\n throw new Error(`Entity [${this.moduleName}.${this.modelName}] with id ${id} not found`);\n }\n\n updateDto.id = id;\n // This class will be extended by the generated service class i.e PersonService\n // The data required to identify the model and module name will be passed from the generate CrudService subclass\n //TODO: Algorithm to create the entity\n // 1. Fire a query and load all the fields in the provided model name for a particular module\n // FIXME This can be optimized to take in module name i.e (handle scenario wherein same model exists in multiple modules)\n let hasMediaFields = false;\n\n const fieldsToProcess = [...model.fields];\n\n // 2. Loop through the fields with a switch statement\n // 3. Handle the fields based on field type\n for (const field of fieldsToProcess) {\n const transformed = await this.validateAndTransformDto(field, updateDto, files, hasMediaFields, isPartialUpdate, isUpdate);\n updateDto = transformed.dto;\n hasMediaFields = transformed.hasMediaFields;\n }\n\n // 5. Save the entity\n // For media, we need to use a storage provider and save the media, then save the associated uri against the entity or media table\n const mergedEntity = this.repo.merge(entity, updateDto);\n const savedEntity = await this.repo.save(mergedEntity) as T;\n\n // 6. Save the media\n if (hasMediaFields) {\n this.saveMedia(model, files, savedEntity);\n }\n return savedEntity;\n }\n\n //TODO: Will the updates be partial i.e PATCH or full i.e PUT\n async delete(id: number, solidRequestContext: any = {}) {\n if (!id) {\n throw new Error('Id is required for update');\n }\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasDeletePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: true,\n mediaStorageProvider: true,\n },\n module: true,\n });\n const entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n if (!entity) {\n throw new Error(`Entity [${this.moduleName}.${this.modelName}] with id ${id} not found`);\n }\n\n // If the model has internationalisation enabled, delete children with defaultEntityLocaleId === this entity's id\n if (model.internationalisation) {\n // Find all child entities where defaultEntityLocaleId === this entity's id\n const childEntities = await this.repo.find({\n where: { defaultEntityLocaleId: id } as any\n });\n\n if (childEntities.length > 0) {\n if (model.enableSoftDelete === true) {\n await this.repo.softRemove(childEntities);\n } else {\n await this.repo.remove(childEntities);\n }\n }\n }\n\n if (model.enableSoftDelete === true) {\n await this.repo.softRemove(entity);\n return this.repo.save(entity);\n } else {\n return this.repo.remove(entity);\n }\n }\n\n private fieldCrudManager(fieldMetadata: FieldMetadata, entityManager: EntityManager, isPartialUpdate: boolean = false, isUpdate: boolean = false): FieldCrudManager {\n const commonOptions = { required: fieldMetadata.required && !isPartialUpdate, fieldName: fieldMetadata.name, isUpdate };\n switch (fieldMetadata.type) {\n case SolidFieldType.shortText: {\n const options = { ...commonOptions, length: fieldMetadata.max, regexPattern: fieldMetadata.regexPattern };\n return new ShortTextFieldCrudManager(options);\n }\n case SolidFieldType.longtext: {\n const options = { ...commonOptions, regexPattern: fieldMetadata.regexPattern };\n return new LongTextFieldCrudManager(options);\n }\n case SolidFieldType.boolean: {\n const options = { ...commonOptions };\n return new BooleanFieldCrudManager(options);\n }\n case SolidFieldType.richText: {\n const options = { ...commonOptions, regexPattern: fieldMetadata.regexPattern };\n return new RichTextFieldCrudManager(options);\n }\n case SolidFieldType.json: {\n const options = { ...commonOptions };\n return new JsonFieldCrudManager(options);\n }\n case SolidFieldType.int: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max };\n return new IntFieldCrudManager(options);\n }\n case SolidFieldType.decimal: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max };\n return new DecimalFieldCrudManager(options);\n }\n case SolidFieldType.bigint: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max };\n return new BigIntFieldCrudManager(options);\n }\n case SolidFieldType.email: {\n const options = { ...commonOptions, max: fieldMetadata.max ?? MAX_EMAIL_LENGTH, regexPattern: fieldMetadata.regexPattern };\n return new EmailFieldCrudManager(options);\n }\n case SolidFieldType.date:\n case SolidFieldType.datetime: {\n const options = { ...commonOptions };\n return new DateFieldCrudManager(options);\n }\n case SolidFieldType.password: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max, regexPattern: fieldMetadata.regexPattern };\n return new PasswordFieldCrudManager(options);\n }\n case SolidFieldType.mediaSingle:\n case SolidFieldType.mediaMultiple: {\n // update will need to delete the existing media and save the new media \n // case 'mediaSingle':\n // Use the EntityController to extract uploaded content & pass to the entity service.\n // If embedded media, then the media uri will saved in the entity table,\n // else the uri will be saved in the media table\n // Plan the media table schema e.g id, uri, storageProvider, entity_id, entity_name, createdAt, updatedAt\n // break;\n // case 'mediaMultiple':\n // Use the EntityController to extract uploaded content & pass to the entity service.\n // If embedded media, then the media uri will saved in the entity table, else the uri will be saved in the media table\n // Plan the media table schema e.g id, uri, storageProvider, entity_id, entity_name, createdAt, updatedAt\n const options = { ...commonOptions, type: fieldMetadata.type as unknown as SolidMediaType };\n return new MediaFieldCrudManager(options);\n }\n case SolidFieldType.relation: {\n // Identify if the field is for the inverse side or not\n if (fieldMetadata.relationType === RelationType.manyToOne) {\n const manyToOneOptions: ManyToOneRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelUserKeyFieldName: fieldMetadata.model.userKeyField?.name,\n modelSingularName: fieldMetadata.model.singularName,\n entityManager,\n }\n return new ManyToOneRelationFieldCrudManager(manyToOneOptions);\n }\n else if (fieldMetadata.relationType === RelationType.oneToMany) {\n const oneToManyOptions: OneToManyRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelSingularName: fieldMetadata.model.singularName,\n entityManager,\n inverseFieldName: fieldMetadata.relationCoModelFieldName,\n inverseRelationCoModelFieldName: fieldMetadata.name,\n }\n return new OneToManyRelationFieldCrudManager(oneToManyOptions);\n }\n else if (fieldMetadata.relationType === RelationType.manyTomany) {\n if (fieldMetadata.isRelationManyToManyOwner) {\n const manyToManyOptions: ManyToManyRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelSingularName: fieldMetadata.model.singularName,\n isInverseSide: false,\n entityManager,\n fieldName: fieldMetadata.name,\n }\n return new ManyToManyRelationFieldCrudManager(manyToManyOptions);\n }\n else {\n const inverseManyToManyOptions: ManyToManyRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelSingularName: fieldMetadata.model.singularName,\n isInverseSide: true,\n entityManager,\n fieldName: fieldMetadata.relationCoModelFieldName,\n relationCoModelFieldName: fieldMetadata.name,\n }\n return new ManyToManyRelationFieldCrudManager(inverseManyToManyOptions);\n }\n }\n else throw new Error('Relation type not supported in crud service');\n // return (fieldMetadata.relationType === 'many-to-one') ? new ManyToOneRelationFieldCrudManager(fieldMetadata, entityManager) : new ManyToManyRelationFieldCrudManager(fieldMetadata, entityManager); //FIXME many-to-many pending\n // ManyToOne -> fieldId. The value is saved as is. No transformation is required\n // OneToMany -> fieldIds. Get the value of the oneToMany field side. No transformation is required (While saving special provision to be made)\n // ManyToMany\n // break;\n }\n case SolidFieldType.selectionStatic: {\n\n // Validation against the selectionStatic values. No transformation is required\n // If the value is not in the selectionStatic values, then throw\n // Also validate against the selectionType\n const options = { ...commonOptions, selectionStaticValues: fieldMetadata.selectionStaticValues, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, isMultiSelect: fieldMetadata.isMultiSelect };\n return new SelectionStaticFieldCrudManager(options);\n }\n case SolidFieldType.selectionDynamic: {// [HOLD]\n // Default implementation using list of values.\n // ISelectionProvider interface to be implemented for dynamic selection\n // dataSource: string; // The name of the selection provider\n // filterSchema : json // This is a custom json object that every data source will handle accordingly. We could validate the query against the selection provider\n // values : string[]; // The values returned by the selection provider\n const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: fieldMetadata.selectionDynamicProviderCtxt, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };\n return new SelectionDynamicFieldCrudManager(options);\n }\n case SolidFieldType.uuid: {\n const options = { ...commonOptions };\n // If no value is provided, then generate a uuid. Add to the dto\n return new UUIDFieldCrudManager(options);\n }\n case SolidFieldType.computed: {\n\n // The value will be computed by the computed provider\n // Invoke the appropriate computed provider, get the value and add to the dto\n const options = { ...commonOptions, computedFieldProvider: fieldMetadata.computedFieldValueProvider, computedFieldValueProviderCtxt: fieldMetadata.computedFieldValueProviderCtxt, computedFieldValueType: fieldMetadata.computedFieldValueType as ComputedFieldValueType, discoveryService: this.discoveryService, skipComputation: this.isSkipComputation(isPartialUpdate, fieldMetadata) };\n return new ComputedFieldCrudManager(options);\n }\n default:\n return new NoOpsFieldCrudManager();\n }\n }\n\n private isSkipComputation(isPartialUpdate: boolean, computedFieldMetadata: FieldMetadata) {\n if (isPartialUpdate) return true; // If it is a partial update, then skip computation\n if (computedFieldMetadata.computedFieldTriggerConfig && computedFieldMetadata.computedFieldTriggerConfig.length > 0) {\n return true; // computedFieldTriggerConfig is a new field introduced as part of the IEntityComputedFieldProvider new interface, so this computation will be skiipped in crud service & will be called in the subscriber instead\n }\n return false; // If it is not a partial update, then do not skip computation\n }\n\n async find(basicFilterDto: BasicFilterDto, solidRequestContext: any = {}) {\n const alias = 'entity';\n // Extract the required keys from the input query\n let { limit, offset, populateMedia, populateGroup, groupFilter } = basicFilterDto;\n const { singularName, internationalisation, draftPublishWorkflow } = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n // Create above query on pincode table using query builder\n var qb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias)\n qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);\n if (internationalisation && draftPublishWorkflow) {\n qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias, internationalisation, draftPublishWorkflow, this.moduleRef);\n }\n\n if (basicFilterDto.groupBy) {\n // Get the records and the count\n const { groupMeta, groupRecords } = await this.handleGroupFind(qb, groupFilter, populateGroup, alias, populateMedia);\n const totalGroups = await this.crudHelperService.countGroupedRecords(qb, basicFilterDto, alias);\n qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);\n\n return {\n meta: {\n \"totalRecords\": totalGroups\n },\n groupMeta,\n groupRecords,\n }\n }\n else {\n // Get the records and the count\n const { meta, records } = await this.handleNonGroupFind(qb, populateMedia, offset, limit, alias);\n return {\n meta,\n records,\n }\n }\n }\n\n private async handleNonGroupFind(qb: SelectQueryBuilder<T>, populateMedia: string[], offset: number, limit: number, alias: string) {\n const [entities, count] = await qb.getManyAndCount();\n\n // Populate the entity with the media\n if (populateMedia && populateMedia.length > 0) {\n await this.handlePopulateMedia(populateMedia, entities);\n }\n\n return this.wrapFindResponse(offset, limit, count, entities);\n }\n\n private async handleGroupFind(qb: SelectQueryBuilder<T>, groupFilter: BasicFilterDto, populateGroup: boolean, alias: string, populateMedia: string[]) {\n const groupByResult = await qb.getRawMany();\n\n const groupMeta = [];\n const groupRecords = [];\n // For each group, get the records and the count\n for (const group of groupByResult) {\n if (populateGroup) {\n let groupByQb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias);\n groupByQb = this.crudHelperService.buildFilterQuery(groupByQb, groupFilter, alias);\n groupByQb = this.crudHelperService.buildGroupByRecordsQuery(groupByQb, group, alias);\n const [entities, count] = await groupByQb.getManyAndCount();\n\n // Populate the entity with the media\n if (populateMedia && populateMedia.length > 0) {\n await this.handlePopulateMedia(populateMedia, entities);\n }\n const groupData = this.wrapFindResponse(groupFilter.offset, groupFilter.limit, count, entities);\n groupRecords.push(this.crudHelperService.createGroupRecords(group, alias, groupData));\n }\n groupMeta.push(this.crudHelperService.createGroupMeta(group, alias));\n }\n return { groupMeta, groupRecords };\n }\n\n private wrapFindResponse(offset: number, limit: number, count: number, entities: T[]) {\n const currentPage = Math.floor(offset / limit) + 1;\n const totalPages = Math.ceil(count / limit);\n\n const nextPage = currentPage < totalPages ? currentPage + 1 : null;\n const prevPage = currentPage > 1 ? currentPage - 1 : null;\n\n const r = {\n meta: {\n totalRecords: count,\n currentPage: currentPage,\n nextPage: nextPage,\n prevPage: prevPage,\n totalPages: totalPages,\n perPage: +limit,\n },\n records: entities\n };\n return r;\n }\n\n private async handlePopulateMedia(populateMedia: string[], entities: T[]) {\n const model = await this.entityManager.getRepository(ModelMetadata).findOne({\n where: {\n singularName: this.modelName,\n },\n relations: ['fields', 'fields.mediaStorageProvider', 'fields.model', 'module'],\n });\n\n // Will iterate through every entity & all populateMedia & call getMediaDetails for each field\n for (const entity of entities) {\n for (const mediaFieldPath of populateMedia) {\n await this.populateMediaObject(mediaFieldPath, model, entity);\n }\n }\n return entities;\n }\n\n // Adds the media with full URL to the entity / nested entity\n private async populateMediaObject(mediaFieldPath: string, model: ModelMetadata, entity: T) {\n if (mediaFieldPath.includes('.')) { // mediaFieldPath is a nested field\n const pathParts = mediaFieldPath.split('.');\n const mediaFieldMetadata = await this.getFieldMetadataRecursively(pathParts, model.fields);\n if (!mediaFieldMetadata) {\n throw new BadRequestException(`Media field ${mediaFieldPath} not found in model ${this.modelName}`);\n }\n\n // We can assume that the media field entity model is already populated as part of the entity data\n const mediaFieldEntities = this.getMediaFieldEntities(entity, pathParts);\n if (!mediaFieldEntities || mediaFieldEntities.length === 0) {\n return;//no need to populate data if relation not exists\n }\n // Populate the media field entities with the full URL\n for (const mediaFieldEntity of mediaFieldEntities) {\n const mediaWithFullUrl = await this.getMediaWithFullUrl(mediaFieldEntity, mediaFieldMetadata);\n this.appendMediaKey(mediaWithFullUrl, mediaFieldEntity, mediaFieldMetadata.name);\n // mediaFieldEntity['_media'][mediaFieldPath] = mediaWithFullUrl\n }\n }\n else {\n // mediaFieldPath is a single field\n const mediaFieldMetadata = model.fields.find(field => field.name === mediaFieldPath);\n if (!mediaFieldMetadata) {\n throw new BadRequestException(`Media field ${mediaFieldPath} not found in model ${this.modelName}`);\n }\n const mediaWithFullUrl = await this.getMediaWithFullUrl(entity, mediaFieldMetadata);\n this.appendMediaKey(mediaWithFullUrl, entity, mediaFieldPath);\n // entity['_media'][mediaFieldPath] = mediaWithFullUrl;\n }\n }\n\n // // Add the media with full URL to the entity\n private appendMediaKey(mediaWithFullUrl: MediaWithFullUrl[], entity: T, mediaFieldPath: string) {\n // if _media key already exists, append the new media to the existing array\n if (entity['_media']) {\n entity['_media'][mediaFieldPath] = mediaWithFullUrl;\n }\n else {\n entity['_media'] = {\n [mediaFieldPath]: mediaWithFullUrl\n };\n }\n }\n\n private getMediaFieldEntities(entity: T, mediaPathParts: string[]): T[] {\n let entityPart = entity;\n for (let i = 0; i < mediaPathParts.length - 1; i++) {\n const pathPart = mediaPathParts[i];\n if (entity[pathPart]) {\n entityPart = entity[pathPart];\n } else {\n throw new BadRequestException(`Media field ${pathPart} not found in entity ${JSON.stringify(entity)}`);\n }\n }\n return isArray(entityPart) ? entityPart : [entityPart];\n }\n\n async getMediaWithFullUrl(mediaEntity: any, mediaFieldMetadata: FieldMetadata): Promise<MediaWithFullUrl[]> {\n const storageProviderMetadata = mediaFieldMetadata.mediaStorageProvider;\n const storageProviderType = storageProviderMetadata.type as MediaStorageProviderType;\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n const mediaDetails = await storageProvider.retrieve(mediaEntity, mediaFieldMetadata);\n return mediaDetails as MediaWithFullUrl[];\n }\n\n async findOne(id: number, query: any, solidRequestContext: any = {}) {\n const { populate = [], fields = [], populateMedia = [] } = query;\n\n // const normalizedFields = this.crudHelperService.normalize(fields);\n const normalizedPopulate = this.crudHelperService.normalize(populate);\n const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);\n\n // if normalizedPopulateMedia, has any nested media paths, then add then to populate excluding the last part\n const additionalPopulate = this.crudHelperService.additionalRelationsRequiredForMediaPopulation(normalizedPopulateMedia);\n // Add the additional populate relations to the normalizedPopulate, if they are not already present\n normalizedPopulate.push(...additionalPopulate.filter((relation) => !normalizedPopulate.includes(relation)));\n\n const model = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, model.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n let entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n },\n relations: normalizedPopulate,\n select: fields,\n });\n if (!entity) {\n throw new Error(`Entity [${this.moduleName}.${this.modelName}] with id ${id} not found`);\n }\n // Populate the entity with the media\n if (normalizedPopulateMedia.length > 0) {\n const populatedEntities = await this.handlePopulateMedia(normalizedPopulateMedia, [entity]);\n entity = populatedEntities[0] as Awaited<T>;\n }\n return entity;\n }\n\n async insertMany(createDtos: any[], filesArray: Express.Multer.File[][] = [], solidRequestContext: any = {}): Promise<T[]> {\n\n\n // if (createDtos.length !== filesArray.length) {\n // throw new BadRequestException('Mismatch between data objects and file arrays.');\n // }\n\n const loadedmodel = await this.loadModel();\n // Check wheather user has create permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n // Fetch model metadata once\n const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: true,\n mediaStorageProvider: true,\n },\n module: true,\n });\n\n // Process each createDto in parallel\n const createAndSavePromises = createDtos.map(async (createDto, index) => {\n const files = []; // TODO, This is set, because we are not supporting files for insertMany currently\n let hasMediaFields = false;\n\n // Process each field\n for (const field of model.fields) {\n const fieldManager: FieldCrudManager = this.fieldCrudManager(field, this.entityManager);\n const validationErrors = await fieldManager.validate(createDto, files);\n if (validationErrors.length > 0) {\n throw new BadRequestException(`Validation errors in ${field.name} are invalid: ${validationErrors.map(e => e.error).join(', ')}`);\n }\n createDto = await fieldManager.transformForCreate(createDto);\n hasMediaFields = hasMediaFields || field.type === 'mediaSingle' || field.type === 'mediaMultiple';\n }\n\n // Save the entity\n const entity = this.repo.create(createDto);\n const savedEntity = await this.repo.save(entity) as T;\n\n //Commented since currently Files are not supported for insertmany\n // if (hasMediaFields) {\n // await this.saveMedia(model, files, savedEntity);\n // }\n\n return savedEntity;\n });\n\n // Await all promises in parallel\n const savedEntities = await Promise.all(createAndSavePromises);\n\n return savedEntities;\n }\n\n async deleteMany(ids: number[], solidRequestContext: any = {}): Promise<any> {\n\n if (!ids || ids.length === 0) {\n throw new Error('At least one ID is required for deletion');\n }\n\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasDeletePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: true,\n mediaStorageProvider: true,\n },\n module: true,\n });\n\n\n\n const removedEntities = [];\n for (let i = 0; i < ids.length; i++) {\n const id = ids[i]\n const entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n removedEntities.push(entity);\n }\n if (model.enableSoftDelete === true) {\n await this.repo.softRemove(removedEntities);\n return this.repo.save(removedEntities);\n } else {\n return this.repo.remove(removedEntities);\n }\n // return removedEntities\n }\n\n async recover(id: number, solidRequestContext: any = {}) {\n try {\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n const softDeletedRows = await this.repo.findOne({\n where: {\n //@ts-ignore\n id, deletedAt: Not(IsNull())\n },\n withDeleted: true,\n });\n\n if (!softDeletedRows) {\n throw new Error('No soft-deleted record found with the given ID.');\n }\n\n await this.repo.update(id, {\n //@ts-ignore\n deletedAt: null, deletedTracker: \"not-deleted\"\n });\n\n return { message: 'Record successfully recovered', data: softDeletedRows };\n } catch (error) {\n if (error instanceof QueryFailedError) {\n if ((error as any).code === '23505') {\n throw new Error('Another record is conflicting with the record you are attempting to Un-Archive, either delete or change the other record so as to avoid this conflict.');\n }\n }\n\n throw new Error(error);\n }\n }\n\n async recoverMany(ids: number[], solidRequestContext: any = {}) {\n try {\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n if (!ids || ids.length === 0) {\n throw new Error(\"No IDs provided for recovery.\");\n }\n\n // Find soft-deleted records matching the given IDs\n const softDeletedRows = await this.repo.find({\n where: {\n //@ts-ignore\n id: In(ids),\n deletedAt: Not(IsNull()),\n },\n withDeleted: true,\n });\n\n if (softDeletedRows.length === 0) {\n throw new Error(\"No matching soft-deleted records found.\");\n }\n\n // Recover the specific records by setting deletedAt to null\n await this.repo.update(\n //@ts-ignore\n { id: In(ids) },\n { deletedAt: null, deletedTracker: \"not-deleted\" }\n );\n\n return { message: \"Selected records successfully recovered\", recoveredIds: ids };\n } catch (error) {\n if (error instanceof QueryFailedError) {\n if ((error as any).code === \"23505\") {\n throw new Error(\n \"Another record is conflicting with the record you are attempting to Un-Archive, either delete or change the other record to avoid this conflict.\"\n );\n }\n }\n\n throw new Error(error);\n }\n }\n\n\n async getFieldMetadataRecursively(pathParts: string[], fields: FieldMetadata[]) {\n if (!pathParts || pathParts.length === 0) {\n throw new BadRequestException('Path parts cannot be empty');\n }\n\n const [currentPart, ...remainingParts] = pathParts;\n const field = fields.find(field => field.name === currentPart);\n\n if (!field) {\n throw new BadRequestException(`Field ${currentPart} not found in model ${this.modelName}`);\n }\n\n // Base case: last part, return the field\n if (remainingParts.length === 0) {\n return field;\n }\n\n if (!field.relationCoModelSingularName) {\n throw new BadRequestException(`Field ${field.name} does not define a relationCoModelSingularName`);\n }\n\n const relationCoModel = await this.entityManager.getRepository(ModelMetadata).findOne({\n where: { singularName: field.relationCoModelSingularName },\n relations: ['fields', 'fields.mediaStorageProvider', 'fields.model'],\n });\n\n if (!relationCoModel) {\n throw new BadRequestException(`Model ${field.relationCoModelSingularName} not found`);\n }\n\n return this.getFieldMetadataRecursively(remainingParts, relationCoModel.fields);\n }\n}\n\n"]}
1
+ {"version":3,"file":"crud.service.js","sourceRoot":"","sources":["../../src/services/crud.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { BadRequestException, Inject, Optional } from \"@nestjs/common\";\nimport { ConfigService, ConfigType } from \"@nestjs/config\";\nimport { DiscoveryService, ModuleRef } from \"@nestjs/core\";\nimport { EntityManager, In, IsNull, Not, QueryFailedError, SelectQueryBuilder } from \"typeorm\";\nimport { Repository } from \"typeorm/repository/Repository\";\nimport { BasicFilterDto } from \"../dtos/basic-filters.dto\";\nimport { ComputedFieldValueType, RelationType, SelectionValueType, SolidFieldType } from \"../dtos/create-field-metadata.dto\";\nimport { MediaStorageProviderType } from \"../dtos/create-media-storage-provider-metadata.dto\";\nimport { FieldMetadata } from \"../entities/field-metadata.entity\";\nimport { ModelMetadata } from \"../entities/model-metadata.entity\";\nimport { BigIntFieldCrudManager } from \"../helpers/field-crud-managers/BigIntFieldCrudManager\";\nimport { BooleanFieldCrudManager } from \"../helpers/field-crud-managers/BooleanFieldCrudManager\";\nimport { ComputedFieldCrudManager } from \"../helpers/field-crud-managers/ComputedFieldCrudManager\";\nimport { DateFieldCrudManager } from \"../helpers/field-crud-managers/DateFieldCrudManager\";\nimport { DecimalFieldCrudManager } from \"../helpers/field-crud-managers/DecimalFieldCrudManager\";\nimport { EmailFieldCrudManager, MAX_EMAIL_LENGTH } from \"../helpers/field-crud-managers/EmailFieldCrudManager\";\nimport { IntFieldCrudManager } from \"../helpers/field-crud-managers/IntFieldCrudManager\";\nimport { JsonFieldCrudManager } from \"../helpers/field-crud-managers/JsonFieldCrudManager\";\nimport { LongTextFieldCrudManager } from \"../helpers/field-crud-managers/LongTextFieldCrudManager\";\nimport { ManyToManyRelationFieldCrudManager, ManyToManyRelationFieldOptions } from \"../helpers/field-crud-managers/ManyToManyRelationFieldCrudManager\";\nimport { ManyToOneRelationFieldCrudManager, ManyToOneRelationFieldOptions } from \"../helpers/field-crud-managers/ManyToOneRelationFieldCrudManager\";\nimport { MediaFieldCrudManager, SolidMediaType } from \"../helpers/field-crud-managers/MediaFieldCrudManager\";\nimport { NoOpsFieldCrudManager } from \"../helpers/field-crud-managers/NoOpsFieldCrudManager\";\nimport { OneToManyRelationFieldCrudManager, OneToManyRelationFieldOptions } from \"../helpers/field-crud-managers/OneToManyRelationFieldCrudManager\";\nimport { PasswordFieldCrudManager } from \"../helpers/field-crud-managers/PasswordFieldCrudManager\";\nimport { RichTextFieldCrudManager } from \"../helpers/field-crud-managers/RichTextFieldCrudManager\";\nimport { SelectionDynamicFieldCrudManager } from \"../helpers/field-crud-managers/SelectionDynamicFieldCrudManager\";\nimport { SelectionStaticFieldCrudManager } from \"../helpers/field-crud-managers/SelectionStaticFieldCrudManager\";\nimport { ShortTextFieldCrudManager } from \"../helpers/field-crud-managers/ShortTextFieldCrudManager\";\nimport { UUIDFieldCrudManager } from \"../helpers/field-crud-managers/UUIDFieldCrudManager\";\nimport { FieldCrudManager, MediaWithFullUrl } from \"../interfaces\";\nimport { CrudHelperService } from \"./crud-helper.service\";\nimport { FileService } from \"./file.service\";\nimport { getMediaStorageProvider } from \"./mediaStorageProviders\";\nimport { ModelMetadataService } from \"./model-metadata.service\";\nimport { ModuleMetadataService } from \"./module-metadata.service\";\nimport { isArray } from \"class-validator\";\n\nexport class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDto, so we get the proper types in our service\n\n constructor(\n readonly modelMetadataService: ModelMetadataService,\n readonly moduleMetadataService: ModuleMetadataService,\n readonly configService: ConfigService,\n readonly fileService: FileService,\n readonly discoveryService: DiscoveryService,\n readonly crudHelperService: CrudHelperService,\n readonly entityManager: EntityManager,\n readonly repo: Repository<T>,\n readonly modelName: string,\n readonly moduleName: string,\n readonly moduleRef: ModuleRef,\n //We can just have the Model Entity here\n ) { }\n\n async create(createDto: any, files: Express.Multer.File[] = [], solidRequestContext: any = {}): Promise<T> {\n // This class will be extended by the generated service class i.e PersonService\n // The data required to identify the model and module name will be passed from the generate CrudService subclass\n //TODO: Algorithm to create the entity\n // 1. Fire a query and load all the fields in the provided model name for a particular module\n // FIXME This can be optimized to take in module name i.e (handle scenario wherein same model exists in multiple modules)\n let hasMediaFields = false;\n\n const model = await this.loadModel();\n // Check wheather user has create permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, model.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n // const inverseRelationFields = await this.loadInverseRelationFields();\n const fieldsToProcess = [...model.fields];\n\n // 2. Loop through the fields with a switch statement\n // 3. Handle the fields based on field type\n for (const field of fieldsToProcess) {\n const transformed = await this.validateAndTransformDto(field, createDto, files, hasMediaFields);\n createDto = transformed.dto;\n hasMediaFields = transformed.hasMediaFields;\n };\n try {\n // 5. Save the entity\n // For media, we need to use a storage provider and save the media, then save the associated uri against the entity or media table\n const entity = this.repo.create(createDto);\n const savedEntity = await this.repo.save(entity) as T;\n\n // 6. Save the media\n if (hasMediaFields) {\n this.saveMedia(model, files, savedEntity);\n }\n return savedEntity;\n } catch (error) {\n if (error instanceof QueryFailedError && error.message.includes('duplicate key value violates unique constraint')) {\n throw new BadRequestException('Duplicate entry. A record with similar unique fields already exists.');\n }\n throw error;\n }\n }\n\n private async loadModel() {\n return await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: {\n userKeyField: true\n },\n mediaStorageProvider: true,\n },\n module: true,\n });\n }\n\n private async validateAndTransformDto(field: FieldMetadata, dto: any, files: Express.Multer.File[], hasMediaFields: boolean, isPartialUpdate: boolean = false, isUpdate: boolean = false) {\n const fieldManager: FieldCrudManager = await this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate);\n const validationErrors = fieldManager.validate(dto, files);\n const errors = (validationErrors instanceof Promise) ? await validationErrors : validationErrors;\n if (errors.length > 0) {\n throw new BadRequestException(`Validation errors in ${field.name} is invalid i.e ${errors.map(e => e.error).join(', ')}`); //FIXME: Better to return a validation error object\n }\n const dtoOrPromise = fieldManager.transformForCreate(dto);\n dto = (dtoOrPromise instanceof Promise) ? await dtoOrPromise : dtoOrPromise;\n hasMediaFields = hasMediaFields || field.type === 'mediaSingle' || field.type === 'mediaMultiple';\n return { dto, hasMediaFields };\n }\n\n //FIXME: Need to make this saving media async. Use queues approach\n private saveMedia(model: ModelMetadata, files: Express.Multer.File[], savedEntity: T) {\n // Get all the media fields in the dto\n\n const mediaFields = model.fields.filter(field => field.type === 'mediaSingle' || field.type === 'mediaMultiple');\n\n // Depending upon media storage provider configured, get the appropriate storage provider\n mediaFields.forEach(async (mediaField) => {\n const media = files.filter(multerFile => multerFile.fieldname === mediaField.name);\n\n // If media is present, then save the media\n if (media.length > 0) {\n const storageProviderMetadata = mediaField.mediaStorageProvider;\n\n // Use the storage provider metadata to get the appropriate storage provider implementation\n const storageProviderType = storageProviderMetadata.type as MediaStorageProviderType;\n\n // Get the storage provider implementation\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n\n //Commented the below code since we will be direclty images from server on call from ui \n // await storageProvider.delete(savedEntity, mediaField);\n await storageProvider.store(media, savedEntity, mediaField);\n }\n });\n }\n\n //TODO: Will the updates be partial i.e PATCH or full i.e PUT\n async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}, isUpdate: boolean = false): Promise<T> {\n if (!id) {\n throw new Error('Id is required for update');\n }\n isUpdate = true;\n const model = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasUpdatePermissionOnModel(solidRequestContext.activeUser, model.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n const entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n if (!entity) {\n throw new Error(`Entity [${this.moduleName}.${this.modelName}] with id ${id} not found`);\n }\n\n updateDto.id = id;\n // This class will be extended by the generated service class i.e PersonService\n // The data required to identify the model and module name will be passed from the generate CrudService subclass\n //TODO: Algorithm to create the entity\n // 1. Fire a query and load all the fields in the provided model name for a particular module\n // FIXME This can be optimized to take in module name i.e (handle scenario wherein same model exists in multiple modules)\n let hasMediaFields = false;\n\n const fieldsToProcess = [...model.fields];\n\n // 2. Loop through the fields with a switch statement\n // 3. Handle the fields based on field type\n for (const field of fieldsToProcess) {\n const transformed = await this.validateAndTransformDto(field, updateDto, files, hasMediaFields, isPartialUpdate, isUpdate);\n updateDto = transformed.dto;\n hasMediaFields = transformed.hasMediaFields;\n }\n\n // 5. Save the entity\n // For media, we need to use a storage provider and save the media, then save the associated uri against the entity or media table\n const mergedEntity = this.repo.merge(entity, updateDto);\n const savedEntity = await this.repo.save(mergedEntity) as T;\n\n // 6. Save the media\n if (hasMediaFields) {\n this.saveMedia(model, files, savedEntity);\n }\n return savedEntity;\n }\n\n //TODO: Will the updates be partial i.e PATCH or full i.e PUT\n async delete(id: number, solidRequestContext: any = {}) {\n if (!id) {\n throw new Error('Id is required for update');\n }\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasDeletePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: true,\n mediaStorageProvider: true,\n },\n module: true,\n });\n const entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n if (!entity) {\n throw new Error(`Entity [${this.moduleName}.${this.modelName}] with id ${id} not found`);\n }\n\n // If the model has internationalisation enabled, delete children with defaultEntityLocaleId === this entity's id\n if (model.internationalisation) {\n // Find all child entities where defaultEntityLocaleId === this entity's id\n const childEntities = await this.repo.find({\n where: { defaultEntityLocaleId: id } as any\n });\n\n if (childEntities.length > 0) {\n if (model.enableSoftDelete === true) {\n await this.repo.softRemove(childEntities);\n } else {\n await this.repo.remove(childEntities);\n }\n }\n }\n\n if (model.enableSoftDelete === true) {\n await this.repo.softRemove(entity);\n return this.repo.save(entity);\n } else {\n return this.repo.remove(entity);\n }\n }\n\n private async fieldCrudManager(fieldMetadata: FieldMetadata, entityManager: EntityManager, isPartialUpdate: boolean = false, isUpdate: boolean = false) {\n const commonOptions = { required: fieldMetadata.required && !isPartialUpdate, fieldName: fieldMetadata.name, isUpdate };\n switch (fieldMetadata.type) {\n case SolidFieldType.shortText: {\n const options = { ...commonOptions, length: fieldMetadata.max, regexPattern: fieldMetadata.regexPattern };\n return new ShortTextFieldCrudManager(options);\n }\n case SolidFieldType.longtext: {\n const options = { ...commonOptions, regexPattern: fieldMetadata.regexPattern };\n return new LongTextFieldCrudManager(options);\n }\n case SolidFieldType.boolean: {\n const options = { ...commonOptions };\n return new BooleanFieldCrudManager(options);\n }\n case SolidFieldType.richText: {\n const options = { ...commonOptions, regexPattern: fieldMetadata.regexPattern };\n return new RichTextFieldCrudManager(options);\n }\n case SolidFieldType.json: {\n const options = { ...commonOptions };\n return new JsonFieldCrudManager(options);\n }\n case SolidFieldType.int: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max };\n return new IntFieldCrudManager(options);\n }\n case SolidFieldType.decimal: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max };\n return new DecimalFieldCrudManager(options);\n }\n case SolidFieldType.bigint: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max };\n return new BigIntFieldCrudManager(options);\n }\n case SolidFieldType.email: {\n const options = { ...commonOptions, max: fieldMetadata.max ?? MAX_EMAIL_LENGTH, regexPattern: fieldMetadata.regexPattern };\n return new EmailFieldCrudManager(options);\n }\n case SolidFieldType.date:\n case SolidFieldType.datetime: {\n const options = { ...commonOptions };\n return new DateFieldCrudManager(options);\n }\n case SolidFieldType.password: {\n const options = { ...commonOptions, min: fieldMetadata.min, max: fieldMetadata.max, regexPattern: fieldMetadata.regexPattern };\n return new PasswordFieldCrudManager(options);\n }\n case SolidFieldType.mediaSingle:\n case SolidFieldType.mediaMultiple: {\n // update will need to delete the existing media and save the new media \n // case 'mediaSingle':\n // Use the EntityController to extract uploaded content & pass to the entity service.\n // If embedded media, then the media uri will saved in the entity table,\n // else the uri will be saved in the media table\n // Plan the media table schema e.g id, uri, storageProvider, entity_id, entity_name, createdAt, updatedAt\n // break;\n // case 'mediaMultiple':\n // Use the EntityController to extract uploaded content & pass to the entity service.\n // If embedded media, then the media uri will saved in the entity table, else the uri will be saved in the media table\n // Plan the media table schema e.g id, uri, storageProvider, entity_id, entity_name, createdAt, updatedAt\n const options = { ...commonOptions, type: fieldMetadata.type as unknown as SolidMediaType };\n return new MediaFieldCrudManager(options);\n }\n case SolidFieldType.relation: {\n // Identify if the field is for the inverse side or not\n if (fieldMetadata.relationType === RelationType.manyToOne) {\n const relationCoModelUserKeyFieldName = await this.getUserKeyFieldNameForModel(fieldMetadata.relationCoModelSingularName);\n const manyToOneOptions: ManyToOneRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n // modelUserKeyFieldName: fieldMetadata.model.userKeyField?.name,\n modelSingularName: fieldMetadata.model.singularName,\n relationCoModelUserKeyFieldName: relationCoModelUserKeyFieldName,\n entityManager,\n }\n return new ManyToOneRelationFieldCrudManager(manyToOneOptions);\n }\n else if (fieldMetadata.relationType === RelationType.oneToMany) {\n const oneToManyOptions: OneToManyRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelSingularName: fieldMetadata.model.singularName,\n entityManager,\n inverseFieldName: fieldMetadata.relationCoModelFieldName,\n inverseRelationCoModelFieldName: fieldMetadata.name,\n }\n return new OneToManyRelationFieldCrudManager(oneToManyOptions);\n }\n else if (fieldMetadata.relationType === RelationType.manyTomany) {\n if (fieldMetadata.isRelationManyToManyOwner) {\n const manyToManyOptions: ManyToManyRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelSingularName: fieldMetadata.model.singularName,\n isInverseSide: false,\n entityManager,\n fieldName: fieldMetadata.name,\n }\n return new ManyToManyRelationFieldCrudManager(manyToManyOptions);\n }\n else {\n const inverseManyToManyOptions: ManyToManyRelationFieldOptions = {\n ...commonOptions,\n relationCoModelSingularName: fieldMetadata.relationCoModelSingularName,\n modelSingularName: fieldMetadata.model.singularName,\n isInverseSide: true,\n entityManager,\n fieldName: fieldMetadata.relationCoModelFieldName,\n relationCoModelFieldName: fieldMetadata.name,\n }\n return new ManyToManyRelationFieldCrudManager(inverseManyToManyOptions);\n }\n }\n else throw new Error('Relation type not supported in crud service');\n // return (fieldMetadata.relationType === 'many-to-one') ? new ManyToOneRelationFieldCrudManager(fieldMetadata, entityManager) : new ManyToManyRelationFieldCrudManager(fieldMetadata, entityManager); //FIXME many-to-many pending\n // ManyToOne -> fieldId. The value is saved as is. No transformation is required\n // OneToMany -> fieldIds. Get the value of the oneToMany field side. No transformation is required (While saving special provision to be made)\n // ManyToMany\n // break;\n }\n case SolidFieldType.selectionStatic: {\n\n // Validation against the selectionStatic values. No transformation is required\n // If the value is not in the selectionStatic values, then throw\n // Also validate against the selectionType\n const options = { ...commonOptions, selectionStaticValues: fieldMetadata.selectionStaticValues, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, isMultiSelect: fieldMetadata.isMultiSelect };\n return new SelectionStaticFieldCrudManager(options);\n }\n case SolidFieldType.selectionDynamic: {// [HOLD]\n // Default implementation using list of values.\n // ISelectionProvider interface to be implemented for dynamic selection\n // dataSource: string; // The name of the selection provider\n // filterSchema : json // This is a custom json object that every data source will handle accordingly. We could validate the query against the selection provider\n // values : string[]; // The values returned by the selection provider\n const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: fieldMetadata.selectionDynamicProviderCtxt, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };\n return new SelectionDynamicFieldCrudManager(options);\n }\n case SolidFieldType.uuid: {\n const options = { ...commonOptions };\n // If no value is provided, then generate a uuid. Add to the dto\n return new UUIDFieldCrudManager(options);\n }\n case SolidFieldType.computed: {\n\n // The value will be computed by the computed provider\n // Invoke the appropriate computed provider, get the value and add to the dto\n const options = { ...commonOptions, computedFieldProvider: fieldMetadata.computedFieldValueProvider, computedFieldValueProviderCtxt: fieldMetadata.computedFieldValueProviderCtxt, computedFieldValueType: fieldMetadata.computedFieldValueType as ComputedFieldValueType, discoveryService: this.discoveryService, skipComputation: this.isSkipComputation(isPartialUpdate, fieldMetadata) };\n return new ComputedFieldCrudManager(options);\n }\n default:\n return new NoOpsFieldCrudManager();\n }\n }\n\n private isSkipComputation(isPartialUpdate: boolean, computedFieldMetadata: FieldMetadata) {\n if (isPartialUpdate) return true; // If it is a partial update, then skip computation\n if (computedFieldMetadata.computedFieldTriggerConfig && computedFieldMetadata.computedFieldTriggerConfig.length > 0) {\n return true; // computedFieldTriggerConfig is a new field introduced as part of the IEntityComputedFieldProvider new interface, so this computation will be skiipped in crud service & will be called in the subscriber instead\n }\n return false; // If it is not a partial update, then do not skip computation\n }\n\n async find(basicFilterDto: BasicFilterDto, solidRequestContext: any = {}) {\n const alias = 'entity';\n // Extract the required keys from the input query\n let { limit, offset, populateMedia, populateGroup, groupFilter } = basicFilterDto;\n const { singularName, internationalisation, draftPublishWorkflow } = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n // Create above query on pincode table using query builder\n var qb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias)\n qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);\n if (internationalisation && draftPublishWorkflow) {\n qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias, internationalisation, draftPublishWorkflow, this.moduleRef);\n }\n\n if (basicFilterDto.groupBy) {\n // Get the records and the count\n const { groupMeta, groupRecords } = await this.handleGroupFind(qb, groupFilter, populateGroup, alias, populateMedia);\n const totalGroups = await this.crudHelperService.countGroupedRecords(qb, basicFilterDto, alias);\n qb = this.crudHelperService.buildFilterQuery(qb, basicFilterDto, alias);\n\n return {\n meta: {\n \"totalRecords\": totalGroups\n },\n groupMeta,\n groupRecords,\n }\n }\n else {\n // Get the records and the count\n const { meta, records } = await this.handleNonGroupFind(qb, populateMedia, offset, limit, alias);\n return {\n meta,\n records,\n }\n }\n }\n\n private async handleNonGroupFind(qb: SelectQueryBuilder<T>, populateMedia: string[], offset: number, limit: number, alias: string) {\n const [entities, count] = await qb.getManyAndCount();\n\n // Populate the entity with the media\n if (populateMedia && populateMedia.length > 0) {\n await this.handlePopulateMedia(populateMedia, entities);\n }\n\n return this.wrapFindResponse(offset, limit, count, entities);\n }\n\n private async handleGroupFind(qb: SelectQueryBuilder<T>, groupFilter: BasicFilterDto, populateGroup: boolean, alias: string, populateMedia: string[]) {\n const groupByResult = await qb.getRawMany();\n\n const groupMeta = [];\n const groupRecords = [];\n // For each group, get the records and the count\n for (const group of groupByResult) {\n if (populateGroup) {\n let groupByQb: SelectQueryBuilder<T> = this.repo.createQueryBuilder(alias);\n groupByQb = this.crudHelperService.buildFilterQuery(groupByQb, groupFilter, alias);\n groupByQb = this.crudHelperService.buildGroupByRecordsQuery(groupByQb, group, alias);\n const [entities, count] = await groupByQb.getManyAndCount();\n\n // Populate the entity with the media\n if (populateMedia && populateMedia.length > 0) {\n await this.handlePopulateMedia(populateMedia, entities);\n }\n const groupData = this.wrapFindResponse(groupFilter.offset, groupFilter.limit, count, entities);\n groupRecords.push(this.crudHelperService.createGroupRecords(group, alias, groupData));\n }\n groupMeta.push(this.crudHelperService.createGroupMeta(group, alias));\n }\n return { groupMeta, groupRecords };\n }\n\n private wrapFindResponse(offset: number, limit: number, count: number, entities: T[]) {\n const currentPage = Math.floor(offset / limit) + 1;\n const totalPages = Math.ceil(count / limit);\n\n const nextPage = currentPage < totalPages ? currentPage + 1 : null;\n const prevPage = currentPage > 1 ? currentPage - 1 : null;\n\n const r = {\n meta: {\n totalRecords: count,\n currentPage: currentPage,\n nextPage: nextPage,\n prevPage: prevPage,\n totalPages: totalPages,\n perPage: +limit,\n },\n records: entities\n };\n return r;\n }\n\n private async handlePopulateMedia(populateMedia: string[], entities: T[]) {\n const model = await this.entityManager.getRepository(ModelMetadata).findOne({\n where: {\n singularName: this.modelName,\n },\n relations: ['fields', 'fields.mediaStorageProvider', 'fields.model', 'module'],\n });\n\n // Will iterate through every entity & all populateMedia & call getMediaDetails for each field\n for (const entity of entities) {\n for (const mediaFieldPath of populateMedia) {\n await this.populateMediaObject(mediaFieldPath, model, entity);\n }\n }\n return entities;\n }\n\n // Adds the media with full URL to the entity / nested entity\n private async populateMediaObject(mediaFieldPath: string, model: ModelMetadata, entity: T) {\n if (mediaFieldPath.includes('.')) { // mediaFieldPath is a nested field\n const pathParts = mediaFieldPath.split('.');\n const mediaFieldMetadata = await this.getFieldMetadataRecursively(pathParts, model.fields);\n if (!mediaFieldMetadata) {\n throw new BadRequestException(`Media field ${mediaFieldPath} not found in model ${this.modelName}`);\n }\n\n // We can assume that the media field entity model is already populated as part of the entity data\n const mediaFieldEntities = this.getMediaFieldEntities(entity, pathParts);\n if (!mediaFieldEntities || mediaFieldEntities.length === 0) {\n return;//no need to populate data if relation not exists\n }\n // Populate the media field entities with the full URL\n for (const mediaFieldEntity of mediaFieldEntities) {\n const mediaWithFullUrl = await this.getMediaWithFullUrl(mediaFieldEntity, mediaFieldMetadata);\n this.appendMediaKey(mediaWithFullUrl, mediaFieldEntity, mediaFieldMetadata.name);\n // mediaFieldEntity['_media'][mediaFieldPath] = mediaWithFullUrl\n }\n }\n else {\n // mediaFieldPath is a single field\n const mediaFieldMetadata = model.fields.find(field => field.name === mediaFieldPath);\n if (!mediaFieldMetadata) {\n throw new BadRequestException(`Media field ${mediaFieldPath} not found in model ${this.modelName}`);\n }\n const mediaWithFullUrl = await this.getMediaWithFullUrl(entity, mediaFieldMetadata);\n this.appendMediaKey(mediaWithFullUrl, entity, mediaFieldPath);\n // entity['_media'][mediaFieldPath] = mediaWithFullUrl;\n }\n }\n\n // // Add the media with full URL to the entity\n private appendMediaKey(mediaWithFullUrl: MediaWithFullUrl[], entity: T, mediaFieldPath: string) {\n // if _media key already exists, append the new media to the existing array\n if (entity['_media']) {\n entity['_media'][mediaFieldPath] = mediaWithFullUrl;\n }\n else {\n entity['_media'] = {\n [mediaFieldPath]: mediaWithFullUrl\n };\n }\n }\n\n private getMediaFieldEntities(entity: T, mediaPathParts: string[]): T[] {\n let entityPart = entity;\n for (let i = 0; i < mediaPathParts.length - 1; i++) {\n const pathPart = mediaPathParts[i];\n if (entity[pathPart]) {\n entityPart = entity[pathPart];\n } else {\n throw new BadRequestException(`Media field ${pathPart} not found in entity ${JSON.stringify(entity)}`);\n }\n }\n return isArray(entityPart) ? entityPart : [entityPart];\n }\n\n async getMediaWithFullUrl(mediaEntity: any, mediaFieldMetadata: FieldMetadata): Promise<MediaWithFullUrl[]> {\n const storageProviderMetadata = mediaFieldMetadata.mediaStorageProvider;\n const storageProviderType = storageProviderMetadata.type as MediaStorageProviderType;\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n const mediaDetails = await storageProvider.retrieve(mediaEntity, mediaFieldMetadata);\n return mediaDetails as MediaWithFullUrl[];\n }\n\n async findOne(id: number, query: any, solidRequestContext: any = {}) {\n const { populate = [], fields = [], populateMedia = [] } = query;\n\n // const normalizedFields = this.crudHelperService.normalize(fields);\n const normalizedPopulate = this.crudHelperService.normalize(populate);\n const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);\n\n // if normalizedPopulateMedia, has any nested media paths, then add then to populate excluding the last part\n const additionalPopulate = this.crudHelperService.additionalRelationsRequiredForMediaPopulation(normalizedPopulateMedia);\n // Add the additional populate relations to the normalizedPopulate, if they are not already present\n normalizedPopulate.push(...additionalPopulate.filter((relation) => !normalizedPopulate.includes(relation)));\n\n const model = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, model.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n let entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n },\n relations: normalizedPopulate,\n select: fields,\n });\n if (!entity) {\n throw new Error(`Entity [${this.moduleName}.${this.modelName}] with id ${id} not found`);\n }\n // Populate the entity with the media\n if (normalizedPopulateMedia.length > 0) {\n const populatedEntities = await this.handlePopulateMedia(normalizedPopulateMedia, [entity]);\n entity = populatedEntities[0] as Awaited<T>;\n }\n return entity;\n }\n\n async insertMany(createDtos: any[], filesArray: Express.Multer.File[][] = [], solidRequestContext: any = {}): Promise<T[]> {\n\n\n // if (createDtos.length !== filesArray.length) {\n // throw new BadRequestException('Mismatch between data objects and file arrays.');\n // }\n\n const loadedmodel = await this.loadModel();\n // Check wheather user has create permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n // Fetch model metadata once\n const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: true,\n mediaStorageProvider: true,\n },\n module: true,\n });\n\n // Process each createDto in parallel\n const createAndSavePromises = createDtos.map(async (createDto, index) => {\n const files = []; // TODO, This is set, because we are not supporting files for insertMany currently\n let hasMediaFields = false;\n\n // Process each field\n for (const field of model.fields) {\n const fieldManager: FieldCrudManager = await this.fieldCrudManager(field, this.entityManager);\n const validationErrors = await fieldManager.validate(createDto, files);\n if (validationErrors.length > 0) {\n throw new BadRequestException(`Validation errors in ${field.name} are invalid: ${validationErrors.map(e => e.error).join(', ')}`);\n }\n createDto = await fieldManager.transformForCreate(createDto);\n hasMediaFields = hasMediaFields || field.type === 'mediaSingle' || field.type === 'mediaMultiple';\n }\n\n // Save the entity\n const entity = this.repo.create(createDto);\n const savedEntity = await this.repo.save(entity) as T;\n\n //Commented since currently Files are not supported for insertmany\n // if (hasMediaFields) {\n // await this.saveMedia(model, files, savedEntity);\n // }\n\n return savedEntity;\n });\n\n // Await all promises in parallel\n const savedEntities = await Promise.all(createAndSavePromises);\n\n return savedEntities;\n }\n\n async deleteMany(ids: number[], solidRequestContext: any = {}): Promise<any> {\n\n if (!ids || ids.length === 0) {\n throw new Error('At least one ID is required for deletion');\n }\n\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasDeletePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {\n fields: {\n model: true,\n mediaStorageProvider: true,\n },\n module: true,\n });\n\n\n\n const removedEntities = [];\n for (let i = 0; i < ids.length; i++) {\n const id = ids[i]\n const entity = await this.repo.findOne({\n where: {\n //@ts-ignore\n id: id,\n }\n });\n removedEntities.push(entity);\n }\n if (model.enableSoftDelete === true) {\n await this.repo.softRemove(removedEntities);\n return this.repo.save(removedEntities);\n } else {\n return this.repo.remove(removedEntities);\n }\n // return removedEntities\n }\n\n async recover(id: number, solidRequestContext: any = {}) {\n try {\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n const softDeletedRows = await this.repo.findOne({\n where: {\n //@ts-ignore\n id, deletedAt: Not(IsNull())\n },\n withDeleted: true,\n });\n\n if (!softDeletedRows) {\n throw new Error('No soft-deleted record found with the given ID.');\n }\n\n await this.repo.update(id, {\n //@ts-ignore\n deletedAt: null, deletedTracker: \"not-deleted\"\n });\n\n return { message: 'Record successfully recovered', data: softDeletedRows };\n } catch (error) {\n if (error instanceof QueryFailedError) {\n if ((error as any).code === '23505') {\n throw new Error('Another record is conflicting with the record you are attempting to Un-Archive, either delete or change the other record so as to avoid this conflict.');\n }\n }\n\n throw new Error(error);\n }\n }\n\n async recoverMany(ids: number[], solidRequestContext: any = {}) {\n try {\n const loadedmodel = await this.loadModel();\n // Check wheather user has update permission for model\n if (solidRequestContext.activeUser) {\n const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);\n if (!hasPermission) {\n throw new BadRequestException('Forbidden');\n }\n }\n\n if (!ids || ids.length === 0) {\n throw new Error(\"No IDs provided for recovery.\");\n }\n\n // Find soft-deleted records matching the given IDs\n const softDeletedRows = await this.repo.find({\n where: {\n //@ts-ignore\n id: In(ids),\n deletedAt: Not(IsNull()),\n },\n withDeleted: true,\n });\n\n if (softDeletedRows.length === 0) {\n throw new Error(\"No matching soft-deleted records found.\");\n }\n\n // Recover the specific records by setting deletedAt to null\n await this.repo.update(\n //@ts-ignore\n { id: In(ids) },\n { deletedAt: null, deletedTracker: \"not-deleted\" }\n );\n\n return { message: \"Selected records successfully recovered\", recoveredIds: ids };\n } catch (error) {\n if (error instanceof QueryFailedError) {\n if ((error as any).code === \"23505\") {\n throw new Error(\n \"Another record is conflicting with the record you are attempting to Un-Archive, either delete or change the other record to avoid this conflict.\"\n );\n }\n }\n\n throw new Error(error);\n }\n }\n\n\n async getFieldMetadataRecursively(pathParts: string[], fields: FieldMetadata[]) {\n if (!pathParts || pathParts.length === 0) {\n throw new BadRequestException('Path parts cannot be empty');\n }\n\n const [currentPart, ...remainingParts] = pathParts;\n const field = fields.find(field => field.name === currentPart);\n\n if (!field) {\n throw new BadRequestException(`Field ${currentPart} not found in model ${this.modelName}`);\n }\n\n // Base case: last part, return the field\n if (remainingParts.length === 0) {\n return field;\n }\n\n if (!field.relationCoModelSingularName) {\n throw new BadRequestException(`Field ${field.name} does not define a relationCoModelSingularName`);\n }\n\n const relationCoModel = await this.entityManager.getRepository(ModelMetadata).findOne({\n where: { singularName: field.relationCoModelSingularName },\n relations: ['fields', 'fields.mediaStorageProvider', 'fields.model'],\n });\n\n if (!relationCoModel) {\n throw new BadRequestException(`Model ${field.relationCoModelSingularName} not found`);\n }\n\n return this.getFieldMetadataRecursively(remainingParts, relationCoModel.fields);\n }\n\n async getUserKeyFieldNameForModel(modelSingularName: string): Promise<string> {\n const model = await this.modelMetadataService.findOneBySingularName(modelSingularName, ['userKeyField']);\n if (!model) {\n throw new BadRequestException(`Model ${modelSingularName} not found`);\n }\n return model.userKeyField?.name || '';\n }\n}\n\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/dashboard.subscriber.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AAEzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAiB,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEzG,qBACa,mBAAoB,YAAW,yBAAyB,CAAC,SAAS,CAAC;IAIxE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,QAAQ,CAAC,2BAA2B,EAAE,2BAA2B;IACjE,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB;IAL/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAGvC,UAAU,EAAE,UAAU,EAC9B,2BAA2B,EAAE,2BAA2B,EACxD,gBAAgB,EAAE,gBAAgB;IAK/C,QAAQ;IAIF,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;IAQzC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;YASjC,qBAAqB;CAqBtC"}
1
+ {"version":3,"file":"dashboard.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/dashboard.subscriber.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAiB,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEzG,qBACa,mBAAoB,YAAW,yBAAyB,CAAC,SAAS,CAAC;IAIxE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,QAAQ,CAAC,2BAA2B,EAAE,2BAA2B;IACjE,QAAQ,CAAC,gBAAgB,EAAE,gBAAgB;IAL/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAGvC,UAAU,EAAE,UAAU,EAC9B,2BAA2B,EAAE,2BAA2B,EACxD,gBAAgB,EAAE,gBAAgB;IAK/C,QAAQ;IAIF,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;IAQzC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,CAAC;YASjC,qBAAqB;CAqBtC"}
@@ -51,7 +51,7 @@ let DashboardSubscriber = class DashboardSubscriber {
51
51
  }
52
52
  const populatedDashboard = await entityManager.findOne(dashboard_entity_1.Dashboard, {
53
53
  where: { id: dashboard.id },
54
- relations: ['module'],
54
+ relations: ['module', 'dashboardVariables', 'questions', 'questions.questionSqlDatasetConfigs'],
55
55
  });
56
56
  if (!populatedDashboard) {
57
57
  this.logger.error(`Dashboard not found for id ${dashboard.id}`);
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/dashboard.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,6CAAmD;AAEnD,mEAA0D;AAC1D,8FAAyF;AAEzF,qEAAkE;AAClE,qCAAyG;AAGlG,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAE5B,YAEI,UAAuC,EAC9B,2BAAwD,EACxD,gBAAkC;QAF1B,eAAU,GAAV,UAAU,CAAY;QAC9B,gCAA2B,GAA3B,2BAA2B,CAA6B;QACxD,qBAAgB,GAAhB,gBAAgB,CAAkB;QAL9B,WAAM,GAAG,IAAI,eAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAOxD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,QAAQ;QACJ,OAAO,4BAAS,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAA6B;QAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YAC7F,OAAO;QACX,CAAC;QACD,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAA6B;QAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YAC7F,OAAO;QACX,CAAC;QAED,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACtF,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,SAAoB,EAAE,aAA4B;QAClF,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,OAAO;QACX,CAAC;QAGD,MAAM,kBAAkB,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,4BAAS,EAAE;YAC9D,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE;YAC3B,SAAS,EAAE,CAAC,QAAQ,CAAC;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;YAChE,OAAO;QACX,CAAC;QAGD,MAAM,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;IAC1E,CAAC;CAEJ,CAAA;AArDY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;IAIJ,WAAA,IAAA,0BAAgB,GAAE,CAAA;qCACU,oBAAU;QACD,4DAA2B;QACtC,oCAAgB;GANtC,mBAAmB,CAqD/B","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await\nimport { Dashboard } from 'src/entities/dashboard.entity';\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { DashboardMapper } from 'src/mappers/dashboard-mapper';\nimport { DashboardService } from 'src/services/dashboard.service';\nimport { DataSource, EntityManager, EntitySubscriberInterface, InsertEvent, UpdateEvent } from \"typeorm\";\n\n@Injectable()\nexport class DashboardSubscriber implements EntitySubscriberInterface<Dashboard> {\n private readonly logger = new Logger(this.constructor.name);\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n readonly dashboardService: DashboardService, // Assuming you have a DashboardService for custom queries\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return Dashboard;\n }\n\n async afterInsert(event: InsertEvent<Dashboard>) {\n if (!event.entity) {\n this.logger.debug('No dashboard entity found in the DashboardSubscriber afterInsert method');\n return;\n }\n await this.saveDashboardToConfig(event.entity, event.queryRunner.manager);\n }\n\n async afterUpdate(event: UpdateEvent<Dashboard>) {\n if (!event.entity) {\n this.logger.debug('No dashboard entity found in the DashboardSubscriber afterInsert method');\n return;\n }\n\n await this.saveDashboardToConfig(event.databaseEntity, event.queryRunner.manager);\n }\n\n private async saveDashboardToConfig(dashboard: Dashboard, entityManager: EntityManager): Promise<void> {\n if (!dashboard || !dashboard.id) {\n this.logger.debug('Dashboard or dashboard id is undefined');\n return;\n }\n\n // Load the dashboard with module relation populated\n const populatedDashboard = await entityManager.findOne(Dashboard, {\n where: { id: dashboard.id },\n relations: ['module'],\n });\n\n if (!populatedDashboard) {\n this.logger.error(`Dashboard not found for id ${dashboard.id}`);\n return;\n }\n\n // Call the saveDashboardToConfig method from the DashboardService\n await this.dashboardService.saveDashboardToConfig(populatedDashboard);\n }\n\n}"]}
1
+ {"version":3,"file":"dashboard.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/dashboard.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,6CAAmD;AACnD,mEAA0D;AAC1D,8FAAyF;AACzF,qEAAkE;AAClE,qCAAyG;AAGlG,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAE5B,YAEI,UAAuC,EAC9B,2BAAwD,EACxD,gBAAkC;QAF1B,eAAU,GAAV,UAAU,CAAY;QAC9B,gCAA2B,GAA3B,2BAA2B,CAA6B;QACxD,qBAAgB,GAAhB,gBAAgB,CAAkB;QAL9B,WAAM,GAAG,IAAI,eAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAOxD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,QAAQ;QACJ,OAAO,4BAAS,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAA6B;QAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YAC7F,OAAO;QACX,CAAC;QACD,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAA6B;QAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;YAC7F,OAAO;QACX,CAAC;QAED,MAAM,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACtF,CAAC;IAEO,KAAK,CAAC,qBAAqB,CAAC,SAAoB,EAAE,aAA4B;QAClF,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,OAAO;QACX,CAAC;QAGD,MAAM,kBAAkB,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,4BAAS,EAAE;YAC9D,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE;YAC3B,SAAS,EAAE,CAAC,QAAQ,EAAC,oBAAoB,EAAE,WAAW,EAAE,qCAAqC,CAAC;SACjG,CAAC,CAAC;QAEH,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;YAChE,OAAO;QACX,CAAC;QAGD,MAAM,IAAI,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;IAC1E,CAAC;CAEJ,CAAA;AArDY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;IAIJ,WAAA,IAAA,0BAAgB,GAAE,CAAA;qCACU,oBAAU;QACD,4DAA2B;QACtC,oCAAgB;GANtC,mBAAmB,CAqD/B","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport { Dashboard } from 'src/entities/dashboard.entity';\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { DashboardService } from 'src/services/dashboard.service';\nimport { DataSource, EntityManager, EntitySubscriberInterface, InsertEvent, UpdateEvent } from \"typeorm\";\n\n@Injectable()\nexport class DashboardSubscriber implements EntitySubscriberInterface<Dashboard> {\n private readonly logger = new Logger(this.constructor.name);\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n readonly dashboardService: DashboardService, // Assuming you have a DashboardService for custom queries\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return Dashboard;\n }\n\n async afterInsert(event: InsertEvent<Dashboard>) {\n if (!event.entity) {\n this.logger.debug('No dashboard entity found in the DashboardSubscriber afterInsert method');\n return;\n }\n await this.saveDashboardToConfig(event.entity, event.queryRunner.manager);\n }\n\n async afterUpdate(event: UpdateEvent<Dashboard>) {\n if (!event.entity) {\n this.logger.debug('No dashboard entity found in the DashboardSubscriber afterInsert method');\n return;\n }\n\n await this.saveDashboardToConfig(event.databaseEntity, event.queryRunner.manager);\n }\n\n private async saveDashboardToConfig(dashboard: Dashboard, entityManager: EntityManager): Promise<void> {\n if (!dashboard || !dashboard.id) {\n this.logger.debug('Dashboard or dashboard id is undefined');\n return;\n }\n\n // Load the dashboard with module relation populated\n const populatedDashboard = await entityManager.findOne(Dashboard, {\n where: { id: dashboard.id },\n relations: ['module','dashboardVariables', 'questions', 'questions.questionSqlDatasetConfigs'],\n });\n\n if (!populatedDashboard) {\n this.logger.error(`Dashboard not found for id ${dashboard.id}`);\n return;\n }\n\n // Call the saveDashboardToConfig method from the DashboardService\n await this.dashboardService.saveDashboardToConfig(populatedDashboard);\n }\n\n}"]}