@solidstarters/solid-core 1.2.143 → 1.2.145

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/config/common.config.d.ts +2 -0
  2. package/dist/config/common.config.d.ts.map +1 -1
  3. package/dist/config/common.config.js +3 -2
  4. package/dist/config/common.config.js.map +1 -1
  5. package/dist/constants/error-messages.d.ts +83 -0
  6. package/dist/constants/error-messages.d.ts.map +1 -0
  7. package/dist/constants/error-messages.js +86 -0
  8. package/dist/constants/error-messages.js.map +1 -0
  9. package/dist/constants/success-messages.d.ts +11 -0
  10. package/dist/constants/success-messages.d.ts.map +1 -0
  11. package/dist/constants/success-messages.js +14 -0
  12. package/dist/constants/success-messages.js.map +1 -0
  13. package/dist/index.d.ts +7 -3
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +10 -4
  16. package/dist/index.js.map +1 -1
  17. package/dist/interfaces.js.map +1 -1
  18. package/dist/jobs/api-email-subscriber.service.d.ts +1 -1
  19. package/dist/jobs/api-email-subscriber.service.d.ts.map +1 -1
  20. package/dist/jobs/api-email-subscriber.service.js +2 -2
  21. package/dist/jobs/api-email-subscriber.service.js.map +1 -1
  22. package/dist/jobs/database/api-email-subscriber-database.service.d.ts +1 -1
  23. package/dist/jobs/database/api-email-subscriber-database.service.d.ts.map +1 -1
  24. package/dist/jobs/database/api-email-subscriber-database.service.js +2 -2
  25. package/dist/jobs/database/api-email-subscriber-database.service.js.map +1 -1
  26. package/dist/jobs/database/email-subscriber-database.service.d.ts +1 -1
  27. package/dist/jobs/database/email-subscriber-database.service.d.ts.map +1 -1
  28. package/dist/jobs/database/email-subscriber-database.service.js +2 -2
  29. package/dist/jobs/database/email-subscriber-database.service.js.map +1 -1
  30. package/dist/jobs/email-subscriber.service.d.ts +1 -1
  31. package/dist/jobs/email-subscriber.service.d.ts.map +1 -1
  32. package/dist/jobs/email-subscriber.service.js +2 -2
  33. package/dist/jobs/email-subscriber.service.js.map +1 -1
  34. package/dist/seeders/seed-data/solid-core-metadata.json +12 -12
  35. package/dist/services/ai-interaction.service.d.ts.map +1 -1
  36. package/dist/services/ai-interaction.service.js +4 -3
  37. package/dist/services/ai-interaction.service.js.map +1 -1
  38. package/dist/services/authentication.service.d.ts +1 -1
  39. package/dist/services/authentication.service.d.ts.map +1 -1
  40. package/dist/services/authentication.service.js +68 -66
  41. package/dist/services/authentication.service.js.map +1 -1
  42. package/dist/services/crud-helper.service.d.ts.map +1 -1
  43. package/dist/services/crud-helper.service.js +3 -2
  44. package/dist/services/crud-helper.service.js.map +1 -1
  45. package/dist/services/crud.service.d.ts.map +1 -1
  46. package/dist/services/crud.service.js +23 -21
  47. package/dist/services/crud.service.js.map +1 -1
  48. package/dist/services/csv.service.d.ts.map +1 -1
  49. package/dist/services/csv.service.js +3 -2
  50. package/dist/services/csv.service.js.map +1 -1
  51. package/dist/services/excel.service.d.ts.map +1 -1
  52. package/dist/services/excel.service.js +3 -2
  53. package/dist/services/excel.service.js.map +1 -1
  54. package/dist/services/export-transaction.service.d.ts.map +1 -1
  55. package/dist/services/export-transaction.service.js +2 -1
  56. package/dist/services/export-transaction.service.js.map +1 -1
  57. package/dist/services/field-metadata.service.d.ts.map +1 -1
  58. package/dist/services/field-metadata.service.js +9 -8
  59. package/dist/services/field-metadata.service.js.map +1 -1
  60. package/dist/services/file.service.d.ts.map +1 -1
  61. package/dist/services/file.service.js +5 -4
  62. package/dist/services/file.service.js.map +1 -1
  63. package/dist/services/import-transaction.service.d.ts.map +1 -1
  64. package/dist/services/import-transaction.service.js +11 -9
  65. package/dist/services/import-transaction.service.js.map +1 -1
  66. package/dist/services/mail/{ElasticEmailService.d.ts → elastic-email.service.d.ts} +1 -1
  67. package/dist/services/mail/elastic-email.service.d.ts.map +1 -0
  68. package/dist/services/mail/{ElasticEmailService.js → elastic-email.service.js} +1 -1
  69. package/dist/services/mail/elastic-email.service.js.map +1 -0
  70. package/dist/services/mail/{SMTPEmailService.d.ts → smtp-email.service.d.ts} +3 -3
  71. package/dist/services/mail/smtp-email.service.d.ts.map +1 -0
  72. package/dist/services/mail/{SMTPEmailService.js → smtp-email.service.js} +8 -6
  73. package/dist/services/mail/smtp-email.service.js.map +1 -0
  74. package/dist/services/media-storage-provider-metadata.service.d.ts.map +1 -1
  75. package/dist/services/media-storage-provider-metadata.service.js +4 -3
  76. package/dist/services/media-storage-provider-metadata.service.js.map +1 -1
  77. package/dist/services/media.service.d.ts.map +1 -1
  78. package/dist/services/media.service.js +2 -1
  79. package/dist/services/media.service.js.map +1 -1
  80. package/dist/services/model-metadata.service.d.ts.map +1 -1
  81. package/dist/services/model-metadata.service.js +11 -10
  82. package/dist/services/model-metadata.service.js.map +1 -1
  83. package/dist/services/module-metadata.service.d.ts.map +1 -1
  84. package/dist/services/module-metadata.service.js +11 -10
  85. package/dist/services/module-metadata.service.js.map +1 -1
  86. package/dist/services/role-metadata.service.d.ts.map +1 -1
  87. package/dist/services/role-metadata.service.js +3 -2
  88. package/dist/services/role-metadata.service.js.map +1 -1
  89. package/dist/services/sql-expression-resolver.service.d.ts.map +1 -1
  90. package/dist/services/sql-expression-resolver.service.js +2 -1
  91. package/dist/services/sql-expression-resolver.service.js.map +1 -1
  92. package/dist/services/user.service.d.ts.map +1 -1
  93. package/dist/services/user.service.js +11 -10
  94. package/dist/services/user.service.js.map +1 -1
  95. package/dist/solid-core.module.d.ts.map +1 -1
  96. package/dist/solid-core.module.js +9 -7
  97. package/dist/solid-core.module.js.map +1 -1
  98. package/dist/tsconfig.tsbuildinfo +1 -1
  99. package/package.json +1 -1
  100. package/src/config/common.config.ts +3 -2
  101. package/src/constants/error-messages.ts +123 -0
  102. package/src/constants/success-messages.ts +13 -0
  103. package/src/index.ts +10 -4
  104. package/src/interfaces.ts +3 -3
  105. package/src/jobs/api-email-subscriber.service.ts +1 -1
  106. package/src/jobs/database/api-email-subscriber-database.service.ts +1 -1
  107. package/src/jobs/database/email-subscriber-database.service.ts +1 -1
  108. package/src/jobs/email-subscriber.service.ts +1 -1
  109. package/src/seeders/seed-data/solid-core-metadata.json +12 -12
  110. package/src/services/ai-interaction.service.ts +4 -3
  111. package/src/services/authentication.service.ts +67 -65
  112. package/src/services/crud-helper.service.ts +3 -2
  113. package/src/services/crud.service.ts +23 -23
  114. package/src/services/csv.service.ts +3 -2
  115. package/src/services/excel.service.ts +3 -2
  116. package/src/services/export-transaction.service.ts +2 -1
  117. package/src/services/field-metadata.service.ts +9 -8
  118. package/src/services/file.service.ts +5 -4
  119. package/src/services/import-transaction.service.ts +11 -9
  120. package/src/services/mail/{SMTPEmailService.ts → smtp-email.service.ts} +7 -5
  121. package/src/services/media-storage-provider-metadata.service.ts +4 -3
  122. package/src/services/media.service.ts +2 -1
  123. package/src/services/model-metadata.service.ts +11 -10
  124. package/src/services/module-metadata.service.ts +11 -10
  125. package/src/services/role-metadata.service.ts +3 -2
  126. package/src/services/sql-expression-resolver.service.ts +2 -1
  127. package/src/services/user.service.ts +11 -10
  128. package/src/solid-core.module.ts +5 -3
  129. package/dist/services/mail/ElasticEmailService.d.ts.map +0 -1
  130. package/dist/services/mail/ElasticEmailService.js.map +0 -1
  131. package/dist/services/mail/SMTPEmailService.d.ts.map +0 -1
  132. package/dist/services/mail/SMTPEmailService.js.map +0 -1
  133. /package/src/services/mail/{ElasticEmailService.ts → elastic-email.service.ts} +0 -0
@@ -1,5 +1,6 @@
1
1
  import { Injectable, Logger } from '@nestjs/common';
2
2
  import { format, parse } from 'fast-csv';
3
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
3
4
  import { PassThrough, Readable } from 'stream';
4
5
 
5
6
  export interface CsvReadOptions {
@@ -24,12 +25,12 @@ export class CsvService {
24
25
  // Validations
25
26
  // If neither headers nor data records function is provided, throw an error
26
27
  if (headers.length === 0 && typeof getDataRecords !== 'function') {
27
- throw new Error('Either headers or data records function must be provided.');
28
+ throw new Error(ERROR_MESSAGES.MISSING_HEADERS_OR_FUNCTION);
28
29
  }
29
30
 
30
31
  // If data records function is provided, chunkSize must be greater than 0
31
32
  if (getDataRecords && chunkSize <= 0) {
32
- throw new Error('Chunk size must be greater than 0 when data records function is provided.');
33
+ throw new Error(ERROR_MESSAGES.INVALID_CHUNK_SIZE);
33
34
  }
34
35
 
35
36
  const passThrough = new PassThrough(); // ✅ Create a streaming pipe
@@ -1,5 +1,6 @@
1
1
  import { Injectable, Logger } from '@nestjs/common';
2
2
  import * as ExcelJS from 'exceljs';
3
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
3
4
  import { PassThrough, Readable } from 'stream';
4
5
 
5
6
 
@@ -28,12 +29,12 @@ export class ExcelService {
28
29
  // Validations
29
30
  // If neither headers nor data records function is provided, throw an error
30
31
  if (headers.length === 0 && typeof getDataRecords !== 'function') {
31
- throw new Error('Either headers or data records function must be provided.');
32
+ throw new Error(ERROR_MESSAGES.MISSING_HEADERS_OR_FUNCTION);
32
33
  }
33
34
 
34
35
  // If data records function is provided, chunkSize must be greater than 0
35
36
  if (getDataRecords && chunkSize <= 0) {
36
- throw new Error('Chunk size must be greater than 0 when data records function is provided.');
37
+ throw new Error(ERROR_MESSAGES.INVALID_CHUNK_SIZE);
37
38
  }
38
39
 
39
40
  const passThrough = new PassThrough(); // Create streaming pipe
@@ -28,6 +28,7 @@ import { getMediaStorageProvider } from './mediaStorageProviders';
28
28
  import { SolidIntrospectService } from './solid-introspect.service';
29
29
  import { ModelMetadata } from 'src/entities/model-metadata.entity';
30
30
  import { UpdateExportTemplateDto } from 'src/dtos/update-export-template.dto';
31
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
31
32
 
32
33
  const EXPORT_CHUNK_SIZE = 100;
33
34
  enum ExportStatus {
@@ -170,7 +171,7 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
170
171
  exportStream = await this.csvService.createCsvStream(dataRecordsFunc, EXPORT_CHUNK_SIZE);
171
172
  break;
172
173
  default:
173
- throw new Error('Invalid export format');
174
+ throw new Error(ERROR_MESSAGES.INVALID_FORMAT('export' + templateFormat));
174
175
  }
175
176
  return exportStream;
176
177
  }
@@ -14,6 +14,7 @@ import { FieldMetadata } from '../entities/field-metadata.entity';
14
14
  import { ModelMetadata } from '../entities/model-metadata.entity';
15
15
  import { ISelectionProviderValues } from '../interfaces';
16
16
  import { CrudHelperService } from './crud-helper.service';
17
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
17
18
 
18
19
 
19
20
  @Injectable()
@@ -61,7 +62,7 @@ export class FieldMetadataService implements OnApplicationBootstrap {
61
62
 
62
63
  async updateInverseField(field: FieldMetadata, fieldRepository: Repository<FieldMetadata>, modelRepository: Repository<ModelMetadata>) {
63
64
  if (!field.model || !field.model.module) {
64
- throw new Error('Model and module are required to update inverse field');
65
+ throw new Error(ERROR_MESSAGES.MODEL_AND_MODULE_REQUIRED_TO_UPDATE_INVERSE_FIELD);
65
66
  }
66
67
  // Update the inverse field in the db
67
68
  const savedInverseField = await this.updateInverseFieldInDb(field, fieldRepository, modelRepository);
@@ -202,13 +203,13 @@ export class FieldMetadataService implements OnApplicationBootstrap {
202
203
 
203
204
  private validateForInverseField(field: FieldMetadata) {
204
205
  if (field.type !== SolidFieldType.relation) {
205
- throw new Error('Only relation fields can have inverse fields');
206
+ throw new Error(ERROR_MESSAGES.INVALID_INVERSE_FIELD_TYPE);
206
207
  }
207
208
  const modelName = field.model.singularName;
208
209
  const moduleName = field.model.module.name;
209
210
 
210
211
  if (!modelName || !moduleName) {
211
- throw new Error('Model name and module name are required to create inverse field');
212
+ throw new Error(ERROR_MESSAGES.MODEL_NAME_AND_MODULE_NAME_REQUIRED_TO_CREATE_INVERSE_FIELD);
212
213
  }
213
214
  return { moduleName, modelName };
214
215
  }
@@ -1037,7 +1038,7 @@ export class FieldMetadataService implements OnApplicationBootstrap {
1037
1038
  },
1038
1039
  });
1039
1040
  if (!entity) {
1040
- throw new NotFoundException(`No field with id #${query.fieldId} exists`);
1041
+ throw new NotFoundException(ERROR_MESSAGES.FIELD_NOT_FOUND(query.fieldId));
1041
1042
  }
1042
1043
 
1043
1044
  // 2. use the field metadata to identify the provider.
@@ -1049,7 +1050,7 @@ export class FieldMetadataService implements OnApplicationBootstrap {
1049
1050
  // 3. get hold of the provider instance from the SolidRegistry
1050
1051
  const selectionProviderInstance = this.solidRegistry.getSelectionProviderInstance(selectionDynamicProvider);
1051
1052
  if (!selectionProviderInstance) {
1052
- throw new NotFoundException(`Field incorrectly configured. No provider with name ${selectionDynamicProvider} registered in backend.`);
1053
+ throw new NotFoundException(ERROR_MESSAGES.PROVIDER_NOT_FOUND(selectionDynamicProvider));
1053
1054
  }
1054
1055
 
1055
1056
  // 4. use the provider to fetch the dynamic values, pass the query string received from the UI..
@@ -1064,7 +1065,7 @@ export class FieldMetadataService implements OnApplicationBootstrap {
1064
1065
  },
1065
1066
  });
1066
1067
  if (!entity) {
1067
- throw new NotFoundException(`No field with id #${query.fieldId} exists`);
1068
+ throw new NotFoundException(ERROR_MESSAGES.FIELD_NOT_FOUND(query.fieldId));
1068
1069
  }
1069
1070
 
1070
1071
  // 2. use the field metadata to identify the provider.
@@ -1076,7 +1077,7 @@ export class FieldMetadataService implements OnApplicationBootstrap {
1076
1077
  // 3. get hold of the provider instance from the SolidRegistry
1077
1078
  const selectionProviderInstance = this.solidRegistry.getSelectionProviderInstance(selectionDynamicProvider);
1078
1079
  if (!selectionProviderInstance) {
1079
- throw new NotFoundException(`Field incorrectly configured. No provider with name ${selectionDynamicProvider} registered in backend.`);
1080
+ throw new NotFoundException(ERROR_MESSAGES.PROVIDER_NOT_FOUND(selectionDynamicProvider));
1080
1081
  }
1081
1082
 
1082
1083
  // 4. use the provider to fetch the dynamic values, pass the query string received from the UI..
@@ -1108,7 +1109,7 @@ export class FieldMetadataService implements OnApplicationBootstrap {
1108
1109
  await fs.writeFile(filePath, updatedContent);
1109
1110
  } catch (error) {
1110
1111
  this.logger.error('File creation failed:', error);
1111
- throw new Error('File creation failed, rolling back transaction'); // Trigger rollback
1112
+ throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback
1112
1113
  }
1113
1114
  }
1114
1115
 
@@ -7,6 +7,7 @@ import commonConfig, { AwsS3Config } from '../config/common.config';
7
7
  import path from 'path';
8
8
  import { Readable } from 'stream';
9
9
  import { getSignedUrl as awsGetSignedUrl } from '@aws-sdk/s3-request-presigner';
10
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
10
11
 
11
12
  @Injectable()
12
13
  export class FileService {
@@ -69,7 +70,7 @@ export class FileService {
69
70
  await this.createDirectoryIfNotExists(destinationPath);
70
71
  await this.writeFile(destinationPath, data);
71
72
  } catch (error) {
72
- throw new Error(`Error copying file: ${error.message}`);
73
+ throw new Error(`${ERROR_MESSAGES.FILE_COPY_ERROR}: ${error.message}`);
73
74
  }
74
75
  }
75
76
 
@@ -114,12 +115,12 @@ export class FileService {
114
115
  return fileName
115
116
 
116
117
  } catch (error) {
117
- throw new Error(`Error copying file: ${error.message}`);
118
+ throw new Error(`${ERROR_MESSAGES.FILE_COPY_ERROR}: ${error.message}`);
118
119
  }
119
120
  }
120
121
 
121
122
  private checkIfS3ClientExists() {
122
- if (!this.s3Client) { throw new Error('S3 Client not initialized. Please check the S3 configuration'); }
123
+ if (!this.s3Client) { throw new Error(ERROR_MESSAGES.S3_CLIENT_NOT_INITIALIZED); }
123
124
  }
124
125
 
125
126
  async copyToS3WithPublic(filePath: string, ContentType: string, fileName: string, bucketName: string): Promise<string> {
@@ -145,7 +146,7 @@ export class FileService {
145
146
  return fileName
146
147
 
147
148
  } catch (error) {
148
- throw new Error(`Error copying file: ${error.message}`);
149
+ throw new Error(`${ERROR_MESSAGES.FILE_COPY_ERROR}: ${error.message}`);
149
150
  }
150
151
  }
151
152
 
@@ -25,6 +25,7 @@ import { ImportTransaction } from '../entities/import-transaction.entity';
25
25
  import { CsvService } from './csv.service';
26
26
  import { ExcelService } from './excel.service';
27
27
  import { SolidIntrospectService } from './solid-introspect.service';
28
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
28
29
 
29
30
  interface ImportTemplateFileInfo {
30
31
  stream: NodeJS.ReadableStream;
@@ -120,7 +121,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
120
121
  populate: ['fields'],
121
122
  });
122
123
  if (!modelMetadata) {
123
- throw new Error(`Model metadata with ID ${modelMetadataId} not found.`);
124
+ throw new Error(ERROR_MESSAGES.MODEL_METADATA_NOT_FOUND(modelMetadataId));
124
125
  }
125
126
  // Create a header row with the display names of the fields, excluding the media fields,computed fields
126
127
  const headers = this.fieldsAllowedForImport(modelMetadata.fields)
@@ -147,7 +148,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
147
148
  mimeType,
148
149
  };
149
150
  } else {
150
- throw new Error(`Unsupported import format: ${format}`);
151
+ throw new Error(ERROR_MESSAGES.INVALID_FORMAT('import' + format));
151
152
  }
152
153
 
153
154
  }
@@ -158,7 +159,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
158
159
  populate: ['fields'],
159
160
  });
160
161
  if (!modelMetadata) {
161
- throw new Error(`Model metadata with ID ${modelMetadataId} not found.`);
162
+ throw new Error(ERROR_MESSAGES.MODEL_METADATA_NOT_FOUND(modelMetadataId));
162
163
  }
163
164
 
164
165
  // Create the standard import instructions
@@ -294,7 +295,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
294
295
  });
295
296
 
296
297
  if (!firstErrorLogEntry) {
297
- throw new BadRequestException(`No error log entries found for import transaction ID ${importTransactionId}.`);
298
+ throw new BadRequestException(ERROR_MESSAGES.NO_ERROR_LOG_FOR_IMPORT(importTransactionId));
298
299
  }
299
300
 
300
301
  // Create the headers for the export file
@@ -384,6 +385,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
384
385
  field.type !== SolidFieldType.password &&
385
386
  field.type !== SolidFieldType.richText &&
386
387
  field.type !== SolidFieldType.uuid &&
388
+ field.relationType !== RelationType.oneToMany &&
387
389
  field.isSystem !== true // Exclude system fields
388
390
  );
389
391
  }
@@ -402,7 +404,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
402
404
  return firstRecord.value;
403
405
  }
404
406
  else { // If the file is neither CSV nor Excel, throw an error
405
- throw new Error(`Unsupported file type: ${mimeType}`);
407
+ throw new Error(ERROR_MESSAGES.INVALID_FORMAT(mimeType));
406
408
  }
407
409
  }
408
410
 
@@ -426,7 +428,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
426
428
  });
427
429
 
428
430
  if (!fileUrlResponse || !fileUrlResponse.data) {
429
- throw new Error(`Failed to read file from URL: ${fileUrl}`);
431
+ throw new Error(ERROR_MESSAGES.FILE_READ_FAILED_FROM_URL(fileUrl));
430
432
  }
431
433
  // fileUrlResponse.data is a Node.js Readable stream
432
434
  return fileUrlResponse.data;
@@ -462,7 +464,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
462
464
  createdErrorLogIds.push(...errorLogIds);
463
465
  }
464
466
  } else { // If the file is neither CSV nor Excel, throw an error
465
- throw new Error(`Unsupported file type: ${mimeType}`);
467
+ throw new Error(ERROR_MESSAGES.INVALID_FORMAT(mimeType));
466
468
  }
467
469
 
468
470
  return {
@@ -529,7 +531,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
529
531
  const modelServiceWrapper = this.introspectService.getProvider(`${classify(modelSingularName)}Service`);
530
532
  const modelService = modelServiceWrapper.instance as CRUDService<any>;
531
533
  if (!modelService) {
532
- throw new Error(`Model service for ${modelSingularName} not found.`);
534
+ throw new Error(ERROR_MESSAGES.MODEL_SERVICE_NOT_FOUND(modelSingularName));
533
535
  }
534
536
  return modelService;
535
537
  }
@@ -639,7 +641,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
639
641
 
640
642
  private async populateDtoForRelations(fieldMetadata: FieldMetadata, record: Record<string, any>, key: string, dtoRecord: Record<string, any>) {
641
643
  if (!fieldMetadata.relationCoModelSingularName) {
642
- throw new Error(`Relation coModelSingularName is not defined for relation field ${fieldMetadata.name}`);
644
+ throw new Error(ERROR_MESSAGES.RELATION_CO_MODEL_NOT_DEFINED_FOR_FIELD(fieldMetadata.name));
643
645
  }
644
646
 
645
647
  const relatedRecordsIds = await this.getRelatedEntityIdsFromUserKeys(fieldMetadata, record, key);
@@ -33,7 +33,7 @@ export class SMTPEMailService implements IMail {
33
33
  });
34
34
  }
35
35
 
36
- async sendEmailUsingTemplate(to: string, templateName: string, templateParams: any, shouldQueueEmails = false, parentEntity = null, parentEntityId = null, attachments: MailAttachment[] = [], cc: string[] = []): Promise<void> {
36
+ async sendEmailUsingTemplate(to: string, templateName: string, templateParams: any, shouldQueueEmails = false, parentEntity = null, parentEntityId = null, attachments: MailAttachment[] = [], cc: string[] = [], bcc: string[] = [], from: string = null): Promise<void> {
37
37
  // Load template and evaluate it.
38
38
  const emailTemplate = await this.emailTemplateService.findOneByName(templateName);
39
39
  if (!emailTemplate) {
@@ -49,18 +49,19 @@ export class SMTPEMailService implements IMail {
49
49
  const subject = subjectTemplate(templateParams);
50
50
 
51
51
  // Finally send the email.
52
- await this.sendEmail(to, subject, body, shouldQueueEmails, parentEntity, parentEntityId, attachments);
52
+ await this.sendEmail(to, subject, body, shouldQueueEmails, parentEntity, parentEntityId, attachments, cc, bcc, from);
53
53
  }
54
54
 
55
- async sendEmail(to: string, subject: string, body: string, shouldQueueEmails = false, parentEntity = null, parentEntityId = null, attachments: MailAttachment[] = [], cc: string[] = []): Promise<void> {
55
+ async sendEmail(to: string, subject: string, body: string, shouldQueueEmails = false, parentEntity = null, parentEntityId = null, attachments: MailAttachment[] = [], cc: string[] = [], bcc: string[] = [], from: string = null): Promise<void> {
56
56
  const message = {
57
57
  payload: {
58
- from: this.commonConfiguration.smtpMail.from,
58
+ from: from || this.commonConfiguration.smtpMail.from,
59
59
  to: to,
60
60
  subject: subject,
61
61
  body: body,
62
62
  attachments: attachments,
63
63
  cc: cc,
64
+ bcc: bcc,
64
65
  },
65
66
  parentEntity: parentEntity,
66
67
  parentEntityId: parentEntityId,
@@ -92,7 +93,7 @@ export class SMTPEMailService implements IMail {
92
93
  }
93
94
 
94
95
  async sendEmailSynchronously(message: QueueMessage<any>): Promise<void> {
95
- const { from, to, subject, body, attachments, cc } = message.payload;
96
+ const { from, to, subject, body, attachments, cc, bcc } = message.payload;
96
97
 
97
98
  const attachmentsList = attachments.map((attachment: MailAttachment) => {
98
99
  const attachmentEntry = {
@@ -113,6 +114,7 @@ export class SMTPEMailService implements IMail {
113
114
  from: from,
114
115
  to: to,
115
116
  cc: cc,
117
+ bcc: bcc,
116
118
  subject: subject,
117
119
  html: body,
118
120
  attachments: attachmentsList,
@@ -5,6 +5,7 @@ import { MediaStorageProviderMetadata } from "../entities/media-storage-provider
5
5
  import { BasicFilterDto } from "../dtos/basic-filters.dto";
6
6
  import { CrudHelperService } from "./crud-helper.service";
7
7
  import { UpdateMediaStorageProviderMetadataDto } from "../dtos/update-media-storage-provider.dto";
8
+ import { ERROR_MESSAGES } from "src/constants/error-messages";
8
9
 
9
10
  @Injectable()
10
11
  export class MediaStorageProviderMetadataService {
@@ -80,7 +81,7 @@ export class MediaStorageProviderMetadataService {
80
81
  relations: relations,
81
82
  });
82
83
  if (!lov) {
83
- throw new NotFoundException(`Media Storage Provider with #${type} not found`);
84
+ throw new NotFoundException(ERROR_MESSAGES.MEDIA_STORAGE_PROVIDER_ID_NOT_FOUND(type));
84
85
  }
85
86
  return lov;
86
87
  }
@@ -118,14 +119,14 @@ export class MediaStorageProviderMetadataService {
118
119
  });
119
120
 
120
121
  if (!entity) {
121
- throw new NotFoundException(`Module ${id} not found`);
122
+ throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(id));
122
123
  }
123
124
  return this.mediaStorageProviderRepo.save(entity);
124
125
  }
125
126
 
126
127
  async deleteMany(ids: number[]): Promise<any> {
127
128
  if (!ids || ids.length === 0) {
128
- throw new Error('At least one ID is required for deletion');
129
+ throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);
129
130
  }
130
131
  const removedEntities = [];
131
132
  for (let i = 0; i < ids.length; i++) {
@@ -18,6 +18,7 @@ import { Media } from 'src/entities/media.entity';
18
18
  import { ModelMetadata } from 'src/entities/model-metadata.entity';
19
19
  import { getMediaStorageProvider } from "./mediaStorageProviders";
20
20
  import { BasicFilterDto } from 'src/dtos/basic-filters.dto';
21
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
21
22
 
22
23
 
23
24
  @Injectable()
@@ -77,7 +78,7 @@ export class MediaService extends CRUDService<Media> {
77
78
  async upload(createDto: any, files: Array<Express.Multer.File>) {
78
79
 
79
80
  if (!files) {
80
- throw new NotFoundException(`File Not Found`);
81
+ throw new NotFoundException(ERROR_MESSAGES.FILE_NOT_FOUND);
81
82
 
82
83
  }
83
84
  const savedMedias = [];
@@ -27,6 +27,7 @@ import { RoleMetadataService } from './role-metadata.service';
27
27
  import { PermissionMetadata } from 'src/entities/permission-metadata.entity';
28
28
  import { classify, dasherize } from '@angular-devkit/core/src/utils/strings';
29
29
  import { DisallowInProduction } from 'src/decorators/disallow-in-production.decorator';
30
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
30
31
 
31
32
  @Injectable()
32
33
  export class ModelMetadataService {
@@ -89,7 +90,7 @@ export class ModelMetadataService {
89
90
  relations: query?.populate, //FIXME: Check with jenender and change to relations to avoid confusion
90
91
  });
91
92
  if (!entity) {
92
- throw new NotFoundException(`entity #${id} not found`);
93
+ throw new NotFoundException(ERROR_MESSAGES.ENTITY_NOT_FOUND(`#${id}`));
93
94
  }
94
95
  return entity;
95
96
  }
@@ -102,7 +103,7 @@ export class ModelMetadataService {
102
103
  relations: relations,
103
104
  });
104
105
  if (!entity) {
105
- throw new NotFoundException(`entity #${singularName} not found`);
106
+ throw new NotFoundException(ERROR_MESSAGES.ENTITY_NOT_FOUND(singularName));
106
107
  }
107
108
  return entity;
108
109
  }
@@ -115,7 +116,7 @@ export class ModelMetadataService {
115
116
  relations: relations,
116
117
  });
117
118
  if (!entity) {
118
- throw new NotFoundException(`entity #${singularName} not found`);
119
+ throw new NotFoundException(ERROR_MESSAGES.ENTITY_NOT_FOUND(singularName));
119
120
  }
120
121
  return entity;
121
122
  }
@@ -289,7 +290,7 @@ export class ModelMetadataService {
289
290
  } catch (error) {
290
291
  // console.error('File creation failed:', error);
291
292
  this.logger.error('File creation failed:', error);
292
- throw new Error('File creation failed, rolling back transaction'); // Trigger rollback
293
+ throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback
293
294
  }
294
295
  }
295
296
 
@@ -307,7 +308,7 @@ export class ModelMetadataService {
307
308
  });
308
309
 
309
310
  if (!existingModel) {
310
- throw new Error(`Model with singular name "${updateModelMetaDataDto.singularName}" not found.`);
311
+ throw new Error(ERROR_MESSAGES.MODEL_NOT_FOUND(updateModelMetaDataDto.singularName));
311
312
  }
312
313
 
313
314
  const updatedModel = modelRepo.merge(existingModel, modelMetaDataWithoutFields);
@@ -470,7 +471,7 @@ export class ModelMetadataService {
470
471
  } catch (error) {
471
472
  // console.error('File creation failed:', error);
472
473
  this.logger.error('File creation failed:', error);
473
- throw new Error('File creation failed, rolling back transaction'); // Trigger rollback
474
+ throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback
474
475
  }
475
476
  }
476
477
 
@@ -507,7 +508,7 @@ export class ModelMetadataService {
507
508
 
508
509
  async deleteMany(ids: number[]): Promise<any> {
509
510
  if (!ids || ids.length === 0) {
510
- throw new Error('At least one ID is required for deletion');
511
+ throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);
511
512
  }
512
513
  const removedEntities = [];
513
514
  for (let i = 0; i < ids.length; i++) {
@@ -909,7 +910,7 @@ export class ModelMetadataService {
909
910
  metaData.menus.push(menu);
910
911
  }
911
912
 
912
- if (notExists(metaData.actions, viewName)) {
913
+ if (notExists(metaData.actions, actionName)) {
913
914
  metaData.actions.push(action);
914
915
  }
915
916
 
@@ -1088,7 +1089,7 @@ export class ModelMetadataService {
1088
1089
 
1089
1090
  async generateRemoveFieldsCode(options: CodeGenerationOptions): Promise<string> {
1090
1091
  if (!options.modelId && !options.modelUserKey) {
1091
- throw new BadRequestException('Model ID or Model Name is required for generating code');
1092
+ throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);
1092
1093
  }
1093
1094
 
1094
1095
  if (!options.fieldIdsForRemoval || options.fieldIdsForRemoval.length === 0) {
@@ -1143,7 +1144,7 @@ export class ModelMetadataService {
1143
1144
 
1144
1145
  async generateModelCode(options: CodeGenerationOptions): Promise<string> {
1145
1146
  if (!options.modelId && !options.modelUserKey) {
1146
- throw new BadRequestException('Model ID or Model Name is required for generating code');
1147
+ throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);
1147
1148
  }
1148
1149
 
1149
1150
  const query = {
@@ -22,6 +22,7 @@ import { CrudHelperService } from './crud-helper.service';
22
22
  import { ModelMetadataService } from './model-metadata.service';
23
23
  import { ModuleMetadataHelperService } from 'src/helpers/module-metadata-helper.service';
24
24
  import { DisallowInProduction } from 'src/decorators/disallow-in-production.decorator';
25
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
25
26
 
26
27
  @Injectable()
27
28
  export class ModuleMetadataService {
@@ -77,7 +78,7 @@ export class ModuleMetadataService {
77
78
 
78
79
  async findOneByUserKey(name: string, relations = {}) {
79
80
  if (!name) {
80
- throw new BadRequestException('name is required for finding entity');
81
+ throw new BadRequestException(ERROR_MESSAGES.ENTITY_NAME_REQUIRED);
81
82
  }
82
83
  const entity = await this.moduleMetadataRepo.findOne({
83
84
  where: {
@@ -90,7 +91,7 @@ export class ModuleMetadataService {
90
91
 
91
92
  async findOne(id: number, relations = {}) {
92
93
  if (!id) {
93
- throw new BadRequestException('ID is required for finding entity');
94
+ throw new BadRequestException(ERROR_MESSAGES.ENTITY_ID_REQUIRED);
94
95
  }
95
96
  const entity = await this.moduleMetadataRepo.findOne({
96
97
  where: {
@@ -99,7 +100,7 @@ export class ModuleMetadataService {
99
100
  relations: relations,
100
101
  });
101
102
  if (!entity) {
102
- throw new NotFoundException(`entity #${id} not found`);
103
+ throw new NotFoundException(ERROR_MESSAGES.ENTITY_NOT_FOUND());
103
104
  }
104
105
  return entity;
105
106
  }
@@ -194,7 +195,7 @@ export class ModuleMetadataService {
194
195
  } catch (error) {
195
196
  // console.error('File creation failed:', error);
196
197
  this.logger.error('File creation failed:', error);
197
- throw new Error('File creation failed, rolling back transaction'); // Trigger rollback
198
+ throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback
198
199
  }
199
200
  }
200
201
 
@@ -221,7 +222,7 @@ export class ModuleMetadataService {
221
222
  });
222
223
 
223
224
  if (!module) {
224
- throw new NotFoundException(`Module ${id} not found`);
225
+ throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(id));
225
226
  }
226
227
  if (files.length > 0) {
227
228
 
@@ -281,7 +282,7 @@ export class ModuleMetadataService {
281
282
  } catch (error) {
282
283
  // console.error('File creation failed:', error);
283
284
  this.logger.error('File creation failed:', error);
284
- throw new Error('File creation failed, rolling back transaction'); // Trigger rollback
285
+ throw new Error(ERROR_MESSAGES.FILE_WRITE_FAILED); // Trigger rollback
285
286
  }
286
287
  }
287
288
 
@@ -320,7 +321,7 @@ export class ModuleMetadataService {
320
321
 
321
322
  async deleteMany(ids: number[]): Promise<any> {
322
323
  if (!ids || ids.length === 0) {
323
- throw new Error('At least one ID is required for deletion');
324
+ throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);
324
325
  }
325
326
  const removedEntities = [];
326
327
  for (let i = 0; i < ids.length; i++) {
@@ -348,13 +349,13 @@ export class ModuleMetadataService {
348
349
  @DisallowInProduction()
349
350
  async generateCode(options: CodeGenerationOptions): Promise<string> {
350
351
  if (!options.moduleId && !options.moduleUserKey) {
351
- throw new BadRequestException('Module ID or Module Name is required for generating code');
352
+ throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);
352
353
  }
353
354
  const module = options.moduleId ? await this.findOne(options.moduleId) : await this.findOneByUserKey(options.moduleUserKey);
354
355
 
355
356
  // Check if the module exists
356
357
  if (!module) {
357
- throw new NotFoundException(`Module ${options.moduleId} not found`);
358
+ throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(options.moduleId));
358
359
  }
359
360
 
360
361
  // Check if the module name already exists and is loaded
@@ -371,7 +372,7 @@ export class ModuleMetadataService {
371
372
 
372
373
  private async generateAddModuleCode(options: CodeGenerationOptions = { dryRun: false }): Promise<string> {
373
374
  if (!options.moduleId && !options.moduleUserKey) {
374
- throw new BadRequestException('Module ID or Module Name is required for generating code');
375
+ throw new BadRequestException(ERROR_MESSAGES.MODEL_REQUIRED_FOR_CODE_GENERATION);
375
376
  }
376
377
  const module = options.moduleId ? await this.findOne(options.moduleId) : await this.findOneByUserKey(options.moduleUserKey);
377
378
 
@@ -12,6 +12,7 @@ import { CrudHelperService } from "src/services/crud-helper.service";
12
12
  import { RoleMetadata } from '../entities/role-metadata.entity';
13
13
  import { PermissionMetadata } from '../entities/permission-metadata.entity';
14
14
  import { CreateRoleMetadataDto } from '../dtos/create-role-metadata.dto';
15
+ import { ERROR_MESSAGES } from 'src/constants/error-messages';
15
16
 
16
17
  @Injectable()
17
18
  export class RoleMetadataService extends CRUDService<RoleMetadata> {
@@ -180,7 +181,7 @@ export class RoleMetadataService extends CRUDService<RoleMetadata> {
180
181
  });
181
182
 
182
183
  if (!role) {
183
- throw new Error(`Role ${roleName} not found.`);
184
+ throw new Error(ERROR_MESSAGES.ROLE_NOT_FOUND(roleName));
184
185
  }
185
186
 
186
187
  // modify the permissions array.
@@ -194,7 +195,7 @@ export class RoleMetadataService extends CRUDService<RoleMetadata> {
194
195
  where: { name },
195
196
  });
196
197
  if (!existingPermission) {
197
- throw new NotFoundException(`Permission ${name} does not exist`)
198
+ throw new NotFoundException(ERROR_MESSAGES.PERMISSION_NOT_EXIST(name));
198
199
  }
199
200
  return existingPermission;
200
201
  }
@@ -1,6 +1,7 @@
1
1
  import { Injectable } from "@nestjs/common";
2
2
  import { SqlExpression, SqlExpressionOperator } from "./question-data-providers/chartjs-sql-data-provider.service";
3
3
  import { RequestContextService } from "./request-context.service";
4
+ import { ERROR_MESSAGES } from "src/constants/error-messages";
4
5
 
5
6
  export interface SqlReplacementResult {
6
7
  rawSql: string;
@@ -117,7 +118,7 @@ export class SqlExpressionResolverService {
117
118
  break;
118
119
 
119
120
  default:
120
- throw new Error(`Unsupported SQL operator: ${expr.operator}`);
121
+ throw new Error(ERROR_MESSAGES.UNSUPPORTED_SQL_OPERATOR(expr.operator));
121
122
  }
122
123
  simplifiedSql = simplifiedSql.replace(placeholder, sqlFragment);
123
124
  }