@solidstarters/solid-core 1.2.142 → 1.2.144

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 (89) hide show
  1. package/dist/constants/error-messages.d.ts +83 -0
  2. package/dist/constants/error-messages.d.ts.map +1 -0
  3. package/dist/constants/error-messages.js +86 -0
  4. package/dist/constants/error-messages.js.map +1 -0
  5. package/dist/constants/success-messages.d.ts +11 -0
  6. package/dist/constants/success-messages.d.ts.map +1 -0
  7. package/dist/constants/success-messages.js +14 -0
  8. package/dist/constants/success-messages.js.map +1 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/services/ai-interaction.service.d.ts.map +1 -1
  14. package/dist/services/ai-interaction.service.js +4 -3
  15. package/dist/services/ai-interaction.service.js.map +1 -1
  16. package/dist/services/authentication.service.d.ts.map +1 -1
  17. package/dist/services/authentication.service.js +66 -64
  18. package/dist/services/authentication.service.js.map +1 -1
  19. package/dist/services/computed-fields/entity/noops-entity-computed-field-provider.service.d.ts.map +1 -1
  20. package/dist/services/computed-fields/entity/noops-entity-computed-field-provider.service.js +18 -2
  21. package/dist/services/computed-fields/entity/noops-entity-computed-field-provider.service.js.map +1 -1
  22. package/dist/services/crud-helper.service.d.ts.map +1 -1
  23. package/dist/services/crud-helper.service.js +3 -2
  24. package/dist/services/crud-helper.service.js.map +1 -1
  25. package/dist/services/crud.service.d.ts.map +1 -1
  26. package/dist/services/crud.service.js +23 -21
  27. package/dist/services/crud.service.js.map +1 -1
  28. package/dist/services/csv.service.d.ts.map +1 -1
  29. package/dist/services/csv.service.js +3 -2
  30. package/dist/services/csv.service.js.map +1 -1
  31. package/dist/services/excel.service.d.ts.map +1 -1
  32. package/dist/services/excel.service.js +3 -2
  33. package/dist/services/excel.service.js.map +1 -1
  34. package/dist/services/export-transaction.service.d.ts.map +1 -1
  35. package/dist/services/export-transaction.service.js +2 -1
  36. package/dist/services/export-transaction.service.js.map +1 -1
  37. package/dist/services/field-metadata.service.d.ts.map +1 -1
  38. package/dist/services/field-metadata.service.js +9 -8
  39. package/dist/services/field-metadata.service.js.map +1 -1
  40. package/dist/services/file.service.d.ts.map +1 -1
  41. package/dist/services/file.service.js +5 -4
  42. package/dist/services/file.service.js.map +1 -1
  43. package/dist/services/import-transaction.service.d.ts.map +1 -1
  44. package/dist/services/import-transaction.service.js +10 -9
  45. package/dist/services/import-transaction.service.js.map +1 -1
  46. package/dist/services/media-storage-provider-metadata.service.d.ts.map +1 -1
  47. package/dist/services/media-storage-provider-metadata.service.js +4 -3
  48. package/dist/services/media-storage-provider-metadata.service.js.map +1 -1
  49. package/dist/services/media.service.d.ts.map +1 -1
  50. package/dist/services/media.service.js +2 -1
  51. package/dist/services/media.service.js.map +1 -1
  52. package/dist/services/model-metadata.service.d.ts.map +1 -1
  53. package/dist/services/model-metadata.service.js +10 -9
  54. package/dist/services/model-metadata.service.js.map +1 -1
  55. package/dist/services/module-metadata.service.d.ts.map +1 -1
  56. package/dist/services/module-metadata.service.js +11 -10
  57. package/dist/services/module-metadata.service.js.map +1 -1
  58. package/dist/services/role-metadata.service.d.ts.map +1 -1
  59. package/dist/services/role-metadata.service.js +3 -2
  60. package/dist/services/role-metadata.service.js.map +1 -1
  61. package/dist/services/sql-expression-resolver.service.d.ts.map +1 -1
  62. package/dist/services/sql-expression-resolver.service.js +2 -1
  63. package/dist/services/sql-expression-resolver.service.js.map +1 -1
  64. package/dist/services/user.service.d.ts.map +1 -1
  65. package/dist/services/user.service.js +11 -10
  66. package/dist/services/user.service.js.map +1 -1
  67. package/dist/tsconfig.tsbuildinfo +1 -1
  68. package/package.json +1 -1
  69. package/src/constants/error-messages.ts +123 -0
  70. package/src/constants/success-messages.ts +13 -0
  71. package/src/index.ts +3 -1
  72. package/src/services/ai-interaction.service.ts +4 -3
  73. package/src/services/authentication.service.ts +66 -64
  74. package/src/services/computed-fields/entity/noops-entity-computed-field-provider.service.ts +4 -0
  75. package/src/services/crud-helper.service.ts +3 -2
  76. package/src/services/crud.service.ts +23 -23
  77. package/src/services/csv.service.ts +3 -2
  78. package/src/services/excel.service.ts +3 -2
  79. package/src/services/export-transaction.service.ts +2 -1
  80. package/src/services/field-metadata.service.ts +9 -8
  81. package/src/services/file.service.ts +5 -4
  82. package/src/services/import-transaction.service.ts +10 -9
  83. package/src/services/media-storage-provider-metadata.service.ts +4 -3
  84. package/src/services/media.service.ts +2 -1
  85. package/src/services/model-metadata.service.ts +10 -9
  86. package/src/services/module-metadata.service.ts +11 -10
  87. package/src/services/role-metadata.service.ts +3 -2
  88. package/src/services/sql-expression-resolver.service.ts +2 -1
  89. package/src/services/user.service.ts +11 -10
@@ -4,6 +4,7 @@ import { classify } from "@angular-devkit/core/src/utils/strings";
4
4
  import { ActiveUserData } from "src/interfaces/active-user-data.interface";
5
5
  import { SolidRegistry } from "src/helpers/solid-registry";
6
6
  import { Logger } from "@nestjs/common";
7
+ import { ERROR_MESSAGES } from "src/constants/error-messages";
7
8
 
8
9
 
9
10
  export class CrudHelperService {
@@ -174,7 +175,7 @@ export class CrudHelperService {
174
175
  const normalizedSort = this.normalize(sort);
175
176
  const normalizedGroupBy = this.normalize(groupBy);
176
177
  if (normalizedGroupBy.length > 1) {
177
- throw new Error('buildFilterQuery: Only 1 Group by field is supported currently');
178
+ throw new Error(ERROR_MESSAGES.GROUP_BY_LIMIT);
178
179
  }
179
180
 
180
181
  // Depending upon the populate option, apply the join clause
@@ -367,7 +368,7 @@ export class CrudHelperService {
367
368
  const groupByField = filteredDto.groupBy;
368
369
 
369
370
  if (!groupByField || (Array.isArray(groupByField) && groupByField.length !== 1)) {
370
- throw new Error('Exactly one groupBy field is required to count grouped records.');
371
+ throw new Error(ERROR_MESSAGES.INVALID_GROUP_BY_COUNT);
371
372
  }
372
373
 
373
374
  const field = Array.isArray(groupByField) ? groupByField[0] : groupByField;
@@ -35,6 +35,8 @@ import { getMediaStorageProvider } from "./mediaStorageProviders";
35
35
  import { ModelMetadataService } from "./model-metadata.service";
36
36
  import { ModuleMetadataService } from "./module-metadata.service";
37
37
  import { isArray } from "class-validator";
38
+ import { ERROR_MESSAGES } from "src/constants/error-messages";
39
+ import { SUCCESS_MESSAGES } from "src/constants/success-messages";
38
40
 
39
41
  export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDto, so we get the proper types in our service
40
42
 
@@ -66,7 +68,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
66
68
  if (solidRequestContext.activeUser) {
67
69
  const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, model.singularName);
68
70
  if (!hasPermission) {
69
- throw new BadRequestException('Forbidden');
71
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
70
72
  }
71
73
  }
72
74
  // const inverseRelationFields = await this.loadInverseRelationFields();
@@ -92,7 +94,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
92
94
  return savedEntity;
93
95
  } catch (error) {
94
96
  if (error instanceof QueryFailedError && error.message.includes('duplicate key value violates unique constraint')) {
95
- throw new BadRequestException('Duplicate entry. A record with similar unique fields already exists.');
97
+ throw new BadRequestException(ERROR_MESSAGES.DUPLICATE_ENTRY);
96
98
  }
97
99
  throw error;
98
100
  }
@@ -153,7 +155,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
153
155
  //TODO: Will the updates be partial i.e PATCH or full i.e PUT
154
156
  async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}, isUpdate: boolean = false): Promise<T> {
155
157
  if (!id) {
156
- throw new Error('Id is required for update');
158
+ throw new Error(ERROR_MESSAGES.ID_REQUIRED_FOR_UPDATE);
157
159
  }
158
160
  isUpdate = true;
159
161
  const model = await this.loadModel();
@@ -161,7 +163,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
161
163
  if (solidRequestContext.activeUser) {
162
164
  const hasPermission = this.crudHelperService.hasUpdatePermissionOnModel(solidRequestContext.activeUser, model.singularName);
163
165
  if (!hasPermission) {
164
- throw new BadRequestException('Forbidden');
166
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
165
167
  }
166
168
  }
167
169
  const entity = await this.repo.findOne({
@@ -207,14 +209,14 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
207
209
  //TODO: Will the updates be partial i.e PATCH or full i.e PUT
208
210
  async delete(id: number, solidRequestContext: any = {}) {
209
211
  if (!id) {
210
- throw new Error('Id is required for update');
212
+ throw new Error(ERROR_MESSAGES.ID_REQUIRED_FOR_DELETE);
211
213
  }
212
214
  const loadedmodel = await this.loadModel();
213
215
  // Check wheather user has update permission for model
214
216
  if (solidRequestContext.activeUser) {
215
217
  const hasPermission = this.crudHelperService.hasDeletePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
216
218
  if (!hasPermission) {
217
- throw new BadRequestException('Forbidden');
219
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
218
220
  }
219
221
  }
220
222
 
@@ -373,7 +375,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
373
375
  return new ManyToManyRelationFieldCrudManager(inverseManyToManyOptions);
374
376
  }
375
377
  }
376
- else throw new Error('Relation type not supported in crud service');
378
+ else throw new Error(ERROR_MESSAGES.RELATION_TYPE_NOT_SUPPORTED);
377
379
  // return (fieldMetadata.relationType === 'many-to-one') ? new ManyToOneRelationFieldCrudManager(fieldMetadata, entityManager) : new ManyToManyRelationFieldCrudManager(fieldMetadata, entityManager); //FIXME many-to-many pending
378
380
  // ManyToOne -> fieldId. The value is saved as is. No transformation is required
379
381
  // OneToMany -> fieldIds. Get the value of the oneToMany field side. No transformation is required (While saving special provision to be made)
@@ -624,7 +626,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
624
626
  if (solidRequestContext.activeUser) {
625
627
  const hasPermission = this.crudHelperService.hasReadPermissionOnModel(solidRequestContext.activeUser, model.singularName);
626
628
  if (!hasPermission) {
627
- throw new BadRequestException('Forbidden');
629
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
628
630
  }
629
631
  }
630
632
 
@@ -659,7 +661,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
659
661
  if (solidRequestContext.activeUser) {
660
662
  const hasPermission = this.crudHelperService.hasCreatePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
661
663
  if (!hasPermission) {
662
- throw new BadRequestException('Forbidden');
664
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
663
665
  }
664
666
  }
665
667
 
@@ -709,7 +711,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
709
711
  async deleteMany(ids: number[], solidRequestContext: any = {}): Promise<any> {
710
712
 
711
713
  if (!ids || ids.length === 0) {
712
- throw new Error('At least one ID is required for deletion');
714
+ throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);
713
715
  }
714
716
 
715
717
  const loadedmodel = await this.loadModel();
@@ -717,7 +719,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
717
719
  if (solidRequestContext.activeUser) {
718
720
  const hasPermission = this.crudHelperService.hasDeletePermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
719
721
  if (!hasPermission) {
720
- throw new BadRequestException('Forbidden');
722
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
721
723
  }
722
724
  }
723
725
  const model = await this.modelMetadataService.findOneBySingularName(this.modelName, {
@@ -757,7 +759,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
757
759
  if (solidRequestContext.activeUser) {
758
760
  const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
759
761
  if (!hasPermission) {
760
- throw new BadRequestException('Forbidden');
762
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
761
763
  }
762
764
  }
763
765
 
@@ -770,7 +772,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
770
772
  });
771
773
 
772
774
  if (!softDeletedRows) {
773
- throw new Error('No soft-deleted record found with the given ID.');
775
+ throw new Error(ERROR_MESSAGES.NO_SOFT_DELETED_RECORD_FOUND);
774
776
  }
775
777
 
776
778
  await this.repo.update(id, {
@@ -778,11 +780,11 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
778
780
  deletedAt: null, deletedTracker: "not-deleted"
779
781
  });
780
782
 
781
- return { message: 'Record successfully recovered', data: softDeletedRows };
783
+ return { message: SUCCESS_MESSAGES.RECORD_RECOVERED, data: softDeletedRows };
782
784
  } catch (error) {
783
785
  if (error instanceof QueryFailedError) {
784
786
  if ((error as any).code === '23505') {
785
- 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.');
787
+ throw new Error(ERROR_MESSAGES.CONFLICTING_RECORD_ON_UNARCHIVE);
786
788
  }
787
789
  }
788
790
 
@@ -797,12 +799,12 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
797
799
  if (solidRequestContext.activeUser) {
798
800
  const hasPermission = this.crudHelperService.hasRecoverPermissionOnModel(solidRequestContext.activeUser, loadedmodel.singularName);
799
801
  if (!hasPermission) {
800
- throw new BadRequestException('Forbidden');
802
+ throw new BadRequestException(ERROR_MESSAGES.FORBIDDEN);
801
803
  }
802
804
  }
803
805
 
804
806
  if (!ids || ids.length === 0) {
805
- throw new Error("No IDs provided for recovery.");
807
+ throw new Error(ERROR_MESSAGES.DELETE_IDS_REQUIRED);
806
808
  }
807
809
 
808
810
  // Find soft-deleted records matching the given IDs
@@ -816,7 +818,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
816
818
  });
817
819
 
818
820
  if (softDeletedRows.length === 0) {
819
- throw new Error("No matching soft-deleted records found.");
821
+ throw new Error(ERROR_MESSAGES.NO_SOFT_DELETED_RECORDS_FOUND);
820
822
  }
821
823
 
822
824
  // Recover the specific records by setting deletedAt to null
@@ -826,13 +828,11 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
826
828
  { deletedAt: null, deletedTracker: "not-deleted" }
827
829
  );
828
830
 
829
- return { message: "Selected records successfully recovered", recoveredIds: ids };
831
+ return { message: SUCCESS_MESSAGES.SELECTED_RECORDS_RECOVERED, recoveredIds: ids };
830
832
  } catch (error) {
831
833
  if (error instanceof QueryFailedError) {
832
834
  if ((error as any).code === "23505") {
833
- throw new Error(
834
- "Another record is conflicting with the record you are attempting to Un-Archive, either delete or change the other record to avoid this conflict."
835
- );
835
+ throw new Error(ERROR_MESSAGES.CONFLICTING_RECORD_ON_UNARCHIVE);
836
836
  }
837
837
  }
838
838
 
@@ -843,7 +843,7 @@ export class CRUDService<T> { // Add two generic value i.e Person,CreatePersonDt
843
843
 
844
844
  async getFieldMetadataRecursively(pathParts: string[], fields: FieldMetadata[]) {
845
845
  if (!pathParts || pathParts.length === 0) {
846
- throw new BadRequestException('Path parts cannot be empty');
846
+ throw new BadRequestException(ERROR_MESSAGES.EMPTY_PATH_PARTS);
847
847
  }
848
848
 
849
849
  const [currentPart, ...remainingParts] = pathParts;
@@ -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
@@ -402,7 +403,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
402
403
  return firstRecord.value;
403
404
  }
404
405
  else { // If the file is neither CSV nor Excel, throw an error
405
- throw new Error(`Unsupported file type: ${mimeType}`);
406
+ throw new Error(ERROR_MESSAGES.INVALID_FORMAT(mimeType));
406
407
  }
407
408
  }
408
409
 
@@ -426,7 +427,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
426
427
  });
427
428
 
428
429
  if (!fileUrlResponse || !fileUrlResponse.data) {
429
- throw new Error(`Failed to read file from URL: ${fileUrl}`);
430
+ throw new Error(ERROR_MESSAGES.FILE_READ_FAILED_FROM_URL(fileUrl));
430
431
  }
431
432
  // fileUrlResponse.data is a Node.js Readable stream
432
433
  return fileUrlResponse.data;
@@ -462,7 +463,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
462
463
  createdErrorLogIds.push(...errorLogIds);
463
464
  }
464
465
  } else { // If the file is neither CSV nor Excel, throw an error
465
- throw new Error(`Unsupported file type: ${mimeType}`);
466
+ throw new Error(ERROR_MESSAGES.INVALID_FORMAT(mimeType));
466
467
  }
467
468
 
468
469
  return {
@@ -529,7 +530,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
529
530
  const modelServiceWrapper = this.introspectService.getProvider(`${classify(modelSingularName)}Service`);
530
531
  const modelService = modelServiceWrapper.instance as CRUDService<any>;
531
532
  if (!modelService) {
532
- throw new Error(`Model service for ${modelSingularName} not found.`);
533
+ throw new Error(ERROR_MESSAGES.MODEL_SERVICE_NOT_FOUND(modelSingularName));
533
534
  }
534
535
  return modelService;
535
536
  }
@@ -639,7 +640,7 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
639
640
 
640
641
  private async populateDtoForRelations(fieldMetadata: FieldMetadata, record: Record<string, any>, key: string, dtoRecord: Record<string, any>) {
641
642
  if (!fieldMetadata.relationCoModelSingularName) {
642
- throw new Error(`Relation coModelSingularName is not defined for relation field ${fieldMetadata.name}`);
643
+ throw new Error(ERROR_MESSAGES.RELATION_CO_MODEL_NOT_DEFINED_FOR_FIELD(fieldMetadata.name));
643
644
  }
644
645
 
645
646
  const relatedRecordsIds = await this.getRelatedEntityIdsFromUserKeys(fieldMetadata, record, key);
@@ -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++) {
@@ -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 = {