@solidstarters/solid-core 1.2.169 → 1.2.171

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 (97) hide show
  1. package/dist/config/iam.config.d.ts +2 -0
  2. package/dist/config/iam.config.d.ts.map +1 -1
  3. package/dist/config/iam.config.js +2 -1
  4. package/dist/config/iam.config.js.map +1 -1
  5. package/dist/controllers/authentication.controller.d.ts.map +1 -1
  6. package/dist/controllers/authentication.controller.js +0 -8
  7. package/dist/controllers/authentication.controller.js.map +1 -1
  8. package/dist/controllers/email-template.controller.d.ts +1 -1
  9. package/dist/controllers/email-template.controller.d.ts.map +1 -1
  10. package/dist/controllers/email-template.controller.js +3 -6
  11. package/dist/controllers/email-template.controller.js.map +1 -1
  12. package/dist/controllers/google-authentication.controller.d.ts +3 -3
  13. package/dist/controllers/google-authentication.controller.d.ts.map +1 -1
  14. package/dist/controllers/google-authentication.controller.js +5 -8
  15. package/dist/controllers/google-authentication.controller.js.map +1 -1
  16. package/dist/controllers/media.controller.d.ts +1 -1
  17. package/dist/controllers/media.controller.d.ts.map +1 -1
  18. package/dist/controllers/media.controller.js +1 -5
  19. package/dist/controllers/media.controller.js.map +1 -1
  20. package/dist/controllers/model-metadata.controller.d.ts.map +1 -1
  21. package/dist/controllers/model-metadata.controller.js +0 -5
  22. package/dist/controllers/model-metadata.controller.js.map +1 -1
  23. package/dist/controllers/otp-authentication.controller.js +0 -3
  24. package/dist/controllers/otp-authentication.controller.js.map +1 -1
  25. package/dist/controllers/service.controller.d.ts +2 -2
  26. package/dist/controllers/service.controller.d.ts.map +1 -1
  27. package/dist/controllers/service.controller.js +3 -7
  28. package/dist/controllers/service.controller.js.map +1 -1
  29. package/dist/controllers/sms-template.controller.d.ts.map +1 -1
  30. package/dist/controllers/sms-template.controller.js +0 -3
  31. package/dist/controllers/sms-template.controller.js.map +1 -1
  32. package/dist/entities/user.entity.d.ts +3 -0
  33. package/dist/entities/user.entity.d.ts.map +1 -1
  34. package/dist/entities/user.entity.js +13 -1
  35. package/dist/entities/user.entity.js.map +1 -1
  36. package/dist/filters/http-exception.filter.js +1 -1
  37. package/dist/filters/http-exception.filter.js.map +1 -1
  38. package/dist/helpers/error-mapper.service.d.ts.map +1 -1
  39. package/dist/helpers/error-mapper.service.js +1 -1
  40. package/dist/helpers/error-mapper.service.js.map +1 -1
  41. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.d.ts +2 -1
  42. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.d.ts.map +1 -1
  43. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.js +3 -3
  44. package/dist/helpers/field-crud-managers/PasswordFieldCrudManager.js.map +1 -1
  45. package/dist/helpers/model-metadata-helper.service.js.map +1 -1
  46. package/dist/passport-strategies/local.strategy.js +1 -1
  47. package/dist/passport-strategies/local.strategy.js.map +1 -1
  48. package/dist/seeders/seed-data/solid-core-metadata.json +43 -0
  49. package/dist/services/authentication.service.d.ts +2 -1
  50. package/dist/services/authentication.service.d.ts.map +1 -1
  51. package/dist/services/authentication.service.js +28 -5
  52. package/dist/services/authentication.service.js.map +1 -1
  53. package/dist/services/bcrypt.service.d.ts +11 -1
  54. package/dist/services/bcrypt.service.d.ts.map +1 -1
  55. package/dist/services/bcrypt.service.js +35 -5
  56. package/dist/services/bcrypt.service.js.map +1 -1
  57. package/dist/services/crud.service.d.ts.map +1 -1
  58. package/dist/services/crud.service.js +2 -1
  59. package/dist/services/crud.service.js.map +1 -1
  60. package/dist/services/export-transaction.service.d.ts +3 -1
  61. package/dist/services/export-transaction.service.d.ts.map +1 -1
  62. package/dist/services/export-transaction.service.js +70 -16
  63. package/dist/services/export-transaction.service.js.map +1 -1
  64. package/dist/services/hashing.service.d.ts +4 -1
  65. package/dist/services/hashing.service.d.ts.map +1 -1
  66. package/dist/services/hashing.service.js.map +1 -1
  67. package/dist/solid-core.module.d.ts.map +1 -1
  68. package/dist/solid-core.module.js +46 -61
  69. package/dist/solid-core.module.js.map +1 -1
  70. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  71. package/dist/subscribers/audit.subscriber.js +1 -1
  72. package/dist/subscribers/audit.subscriber.js.map +1 -1
  73. package/dist/tsconfig.tsbuildinfo +1 -1
  74. package/package.json +1 -1
  75. package/src/config/iam.config.ts +2 -1
  76. package/src/controllers/authentication.controller.ts +8 -10
  77. package/src/controllers/email-template.controller.ts +7 -10
  78. package/src/controllers/google-authentication.controller.ts +9 -10
  79. package/src/controllers/media.controller.ts +5 -6
  80. package/src/controllers/model-metadata.controller.ts +5 -6
  81. package/src/controllers/otp-authentication.controller.ts +2 -2
  82. package/src/controllers/service.controller.ts +8 -9
  83. package/src/controllers/sms-template.controller.ts +3 -4
  84. package/src/entities/user.entity.ts +9 -0
  85. package/src/filters/http-exception.filter.ts +1 -1
  86. package/src/helpers/error-mapper.service.ts +1 -35
  87. package/src/helpers/field-crud-managers/PasswordFieldCrudManager.ts +4 -3
  88. package/src/helpers/model-metadata-helper.service.ts +1 -1
  89. package/src/passport-strategies/local.strategy.ts +1 -1
  90. package/src/seeders/seed-data/solid-core-metadata.json +43 -0
  91. package/src/services/authentication.service.ts +32 -3
  92. package/src/services/bcrypt.service.ts +45 -7
  93. package/src/services/crud.service.ts +2 -1
  94. package/src/services/export-transaction.service.ts +118 -55
  95. package/src/services/hashing.service.ts +5 -2
  96. package/src/solid-core.module.ts +59 -61
  97. package/src/subscribers/audit.subscriber.ts +6 -1
@@ -29,6 +29,7 @@ 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
31
  import { ERROR_MESSAGES } from 'src/constants/error-messages';
32
+ import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
32
33
 
33
34
  const EXPORT_CHUNK_SIZE = 100;
34
35
  enum ExportStatus {
@@ -71,20 +72,22 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
71
72
  @InjectRepository(FieldMetadata, 'default')
72
73
  readonly fieldRepo: Repository<FieldMetadata>,
73
74
  @InjectRepository(ModelMetadata, 'default')
74
- readonly ModelMetadataRepo : Repository<ModelMetadata>,
75
- readonly moduleRef: ModuleRef
75
+ readonly ModelMetadataRepo: Repository<ModelMetadata>,
76
+ readonly moduleRef: ModuleRef,
77
+ private readonly modelMetadataHelperService: ModelMetadataHelperService,
78
+
76
79
  ) {
77
- super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService, entityManager, repo, 'exportTransaction', 'solid-core',moduleRef);
80
+ super(modelMetadataService, moduleMetadataService, configService, fileService, discoveryService, crudHelperService, entityManager, repo, 'exportTransaction', 'solid-core', moduleRef);
78
81
  }
79
82
 
80
83
  // Return the export stream
81
- async triggerExportSync(id: number, exportTransactionEntity: any, updateDto: UpdateExportTemplateDto , filters: any): Promise<ExportTransactionFileInfo> {
84
+ async triggerExportSync(id: number, exportTransactionEntity: any, updateDto: UpdateExportTemplateDto, filters: any): Promise<ExportTransactionFileInfo> {
82
85
  try {
83
86
  // const loadedExportTransaction = await this.loadExportTransaction(id);
84
87
  // from updateDto, get modelId and get modelMetadata
85
88
  const modeldata = await this.ModelMetadataRepo.findOne({
86
- where: { id: updateDto?.modelMetadataId},
87
- relations: { fields: true},
89
+ where: { id: updateDto?.modelMetadataId },
90
+ relations: { fields: true },
88
91
  })
89
92
  const modelName = modeldata?.singularName;
90
93
  const modelTemplateName = modelName;
@@ -102,13 +105,13 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
102
105
  }
103
106
 
104
107
  // Store the export stream using the appropriate storage provider
105
- async triggerExportAsync(id: number, exportTransactionEntity: any, updateDto: UpdateExportTemplateDto, filters:any): Promise<void> {
108
+ async triggerExportAsync(id: number, exportTransactionEntity: any, updateDto: UpdateExportTemplateDto, filters: any): Promise<void> {
106
109
  try {
107
110
  // const loadedExportTransaction = await this.loadExportTransaction(id)
108
111
  // from updateDto, get modelId and get modelMetadata
109
112
  const modeldata = await this.ModelMetadataRepo.findOne({
110
- where: { id: updateDto?.modelMetadataId},
111
- relations: { fields: true},
113
+ where: { id: updateDto?.modelMetadataId },
114
+ relations: { fields: true },
112
115
  })
113
116
  const modelName = modeldata?.singularName;
114
117
  const modelTemplateName = modelName;
@@ -129,7 +132,7 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
129
132
  private async loadExportTransaction(id: number) {
130
133
  return await this.repo.findOne({
131
134
  where: { id: id },
132
- relations: { exportTemplate: { modelMetadata: {fields: true} }},
135
+ relations: { exportTemplate: { modelMetadata: { fields: true } } },
133
136
  }
134
137
  );
135
138
  }
@@ -138,15 +141,15 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
138
141
  await this.repo.update(id, { status, error });
139
142
  }
140
143
 
141
- private async getExportStreamDetails(modelName: string, templateName: string, fields:any, modelData:any, templateFormat:string, id:number, exportTransaction: any, filters: any) {
144
+ private async getExportStreamDetails(modelName: string, templateName: string, fields: any, modelData: any, templateFormat: string, id: number, exportTransaction: any, filters: any) {
142
145
  // Get the columns which need to be exported & the model id
143
146
  // const fields = JSON.parse(exportTransaction.exportTemplate.fields);
144
147
 
145
148
  // // Get the appropriate service for the model by trying to fetch a model service matching a particular name
146
149
  // const modelName = exportTransaction.exportTemplate.modelMetadata.singularName;
147
- const modelService = this.introspectService.getProvider(`${classify(modelName)}Service`);
150
+ const modelService = this.introspectService.getProvider(`${classify(modelName)}Service`);
148
151
  // const templateName = exportTransaction.exportTemplate.templateName;
149
- const uuid = String(id); //TODO can be renamed to exportTransactionUUID
152
+ const uuid = String(id); //TODO can be renamed to exportTransactionUUID
150
153
  // const modelData = exportTransaction.exportTemplate.modelMetadata;
151
154
 
152
155
  // Get the data records function
@@ -208,17 +211,21 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
208
211
  return (fileFormat === ExportFormat.EXCEL) ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' : 'text/csv';
209
212
  }
210
213
 
211
- private async getDataRecordsFunc(fields: any, modelService: InstanceWrapper<any>, modelMetadata: any, filters:any): Promise<(chunkIndex: number, chunkSize: number) => Promise<any[]>> {
212
- // Return a function which will take the chunkIndex & chunkSize and return the data
213
- // Get the relation fields to populate
214
- const relatedFieldNames = modelMetadata?.fields
215
- .filter((field: { relationType: any; }) => field.relationType !== null)
216
- .map((field: { name: any; }) => field.name);
214
+ private async getDataRecordsFunc(fields: any, modelService: InstanceWrapper<any>, modelMetadata: any, filters: any): Promise<(chunkIndex: number, chunkSize: number) => Promise<any[]>> {
215
+ //Load all possible fields for the model
216
+ const allModelFields = await this.modelMetadataHelperService.loadFieldHierarchy(
217
+ modelMetadata.singularName,
218
+ );
219
+
220
+ // Filter only the fields requested in the export payload
221
+ const modelFields = allModelFields.filter((f: any) =>
222
+ fields.includes(f.name),
223
+ );
217
224
 
218
225
  //Get the model metadata of relation field with userKey details
219
226
  const relatedModelsUserKeyMap = new Map<string, string>();
220
- for (const field of modelMetadata?.fields || []) {
221
- if (field.relationType && field.relationCoModelSingularName && fields.includes(field.name)) {
227
+ for (const field of modelFields) {
228
+ if (field.relationType && field.relationCoModelSingularName) {
222
229
  const relatedModelMetadata = await this.ModelMetadataRepo.findOne({
223
230
  where: { singularName: field.relationCoModelSingularName },
224
231
  relations: ['userKeyField'],
@@ -230,12 +237,24 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
230
237
  }
231
238
  }
232
239
 
240
+ // Build fieldName -> displayName map
241
+ const fieldNameToDisplayName = new Map<string, string>();
242
+ for (const field of modelFields || []) {
243
+ if (field.name) {
244
+ fieldNameToDisplayName.set(field.name, field.displayName ?? field.name);
245
+ }
246
+ }
247
+
248
+
233
249
  return async (chunkIndex: number, chunkSize: number) => {
234
250
  const offset = chunkIndex * chunkSize;
235
251
  const recordFilterDto: BasicFilterDto = {
236
252
  limit: chunkSize,
237
253
  offset,
238
- populate: relatedFieldNames
254
+ //only contains relational fields (so TypeORM includes relations in the result).
255
+ populate: modelFields
256
+ .filter((f: any) => f.relationType !== null)
257
+ .map((f: any) => f.name),
239
258
  };
240
259
  const cleanedFilters = cleanNullsFromObject(filters);
241
260
 
@@ -243,43 +262,87 @@ export class ExportTransactionService extends CRUDService<ExportTransaction> {
243
262
  recordFilterDto.filters = cleanedFilters;
244
263
  }
245
264
 
246
- //Get the non relation fields which are in fields array passed to this function
247
- const nonRelationalFieldSet = new Set(
248
- modelMetadata?.fields
249
- .filter((field: { name: any; relationType: any; }) => fields.includes(field.name) && field.relationType === null)
250
- .map((field: { name: any; }) => field.name)
251
- );
252
265
  const data = await modelService.instance.find(recordFilterDto);
253
266
  const records = data.records ?? [];
254
- const cleanedRecords = records.map((record: Record<string, any>) => {
255
- const newRecord: Record<string, any> = {};
256
-
257
- // Include non-relational fields
258
- for (const key of nonRelationalFieldSet as Set<string>) {
259
- newRecord[key] = record[key];
260
- }
261
-
262
- // Include userKey from each related field
263
- for (const [relatedFieldName, userKeyFieldName] of relatedModelsUserKeyMap.entries()) {
264
- const relatedData = record[relatedFieldName];
265
-
266
- if (Array.isArray(relatedData)) {
267
- // For many-to-many or one-to-many
268
- const values = relatedData.map(item => item?.[userKeyFieldName]).filter(Boolean);
269
- newRecord[relatedFieldName] = values.join(', ');
270
- } else if (relatedData && typeof relatedData === 'object') {
271
- // For many-to-one or one-to-one
272
- newRecord[relatedFieldName] = relatedData?.[userKeyFieldName] ?? null;
273
- } else {
274
- newRecord[relatedFieldName] = null;
267
+ const cleanedRecords = records.map((record: Record<string, any>) => {
268
+ const newRecord: Record<string, any> = {};
269
+
270
+ // Include non-relational fields
271
+ for (const field of modelFields) {
272
+ if (!field.relationType) {
273
+ // newRecord[field.name] = record[field.name];
274
+ const displayKey = fieldNameToDisplayName.get(field.name) ?? field.name;
275
+ const fieldMeta = modelFields.find(f => f.name === field.name);
276
+
277
+ if ((fieldMeta?.type === 'datetime' || fieldMeta?.type === 'date') && record[field.name]) {
278
+ newRecord[displayKey] = new Date(record[field.name]).toISOString();
279
+ } else {
280
+ newRecord[displayKey] = record[field.name];
281
+ }
282
+ }
275
283
  }
276
- }
277
-
278
- return newRecord;
279
- });
280
- return cleanedRecords
284
+
285
+ // Include userKey from each related field
286
+ for (const [relatedFieldName, userKeyFieldName] of relatedModelsUserKeyMap.entries()) {
287
+ const relatedData = record[relatedFieldName];
288
+ const displayKey = fieldNameToDisplayName.get(relatedFieldName) ?? relatedFieldName;
289
+
290
+ if (Array.isArray(relatedData)) {
291
+ // For many-to-many or one-to-many
292
+ const values = relatedData
293
+ .map(item => {
294
+ let val = item?.[userKeyFieldName];
295
+ const relatedFieldMeta = modelFields.find(f => f.name === relatedFieldName);
296
+ if ((relatedFieldMeta?.type === 'datetime' || relatedFieldMeta?.type === 'date') && val) {
297
+ val = new Date(val).toISOString();
298
+ }
299
+ return val;
300
+ })
301
+ .filter(Boolean);
302
+ newRecord[displayKey] = values.join(', ');
303
+ } else if (relatedData && typeof relatedData === 'object') {
304
+ // For many-to-one or one-to-one
305
+ newRecord[relatedFieldName] = relatedData?.[userKeyFieldName] ?? null;
306
+ } else {
307
+ newRecord[displayKey] = null;
308
+ }
309
+ }
310
+
311
+ // Include userKey from each related field (with displayName)
312
+ for (const [relatedFieldName, userKeyFieldName] of relatedModelsUserKeyMap.entries()) {
313
+ const relatedData = record[relatedFieldName];
314
+ const displayKey = fieldNameToDisplayName.get(relatedFieldName) ?? relatedFieldName;
315
+
316
+ if (Array.isArray(relatedData)) {
317
+ // For many-to-many or one-to-many
318
+ const values = relatedData
319
+ .map(item => {
320
+ const val = item?.[userKeyFieldName];
321
+ // Convert datetime to ISO if needed
322
+ const relatedFieldMeta = modelFields.find(f => f.name === relatedFieldName);
323
+ if ((relatedFieldMeta?.type === 'datetime' || relatedFieldMeta?.type === 'date') && val) {
324
+ return new Date(val).toISOString();
325
+ }
326
+ return val;
327
+ })
328
+ .filter(Boolean);
329
+ newRecord[displayKey] = values.join(', ');
330
+ } else if (relatedData && typeof relatedData === 'object') {
331
+ let val = relatedData?.[userKeyFieldName] ?? null;
332
+ const relatedFieldMeta = modelFields.find(f => f.name === relatedFieldName);
333
+ if ((relatedFieldMeta?.type === 'datetime' || relatedFieldMeta?.type === 'date') && val) {
334
+ val = new Date(val).toISOString();
335
+ }
336
+ newRecord[displayKey] = val;
337
+ } else {
338
+ newRecord[displayKey] = null;
339
+ }
340
+ }
341
+ return newRecord;
342
+ });
343
+ return cleanedRecords
344
+ }
281
345
  }
282
- }
283
346
 
284
347
  async toDto(data: Partial<CreateExportTransactionDto>): Promise<CreateExportTransactionDto> {
285
348
  const dto = new CreateExportTransactionDto(data);
@@ -3,5 +3,8 @@ import { Injectable } from '@nestjs/common';
3
3
  @Injectable()
4
4
  export abstract class HashingService {
5
5
  abstract hash(data: string | Buffer): Promise<string>;
6
- abstract compare(data: string | Buffer, encrypted: string): Promise<boolean>;
7
- }
6
+ abstract compare(data: string | Buffer, hash: string, hashVersion: number): Promise<boolean>;
7
+ abstract needsRehash(hash: string, hashVersion: number): boolean;
8
+ abstract currentVersion(): number;
9
+ abstract name(): string;
10
+ }
@@ -83,16 +83,16 @@ import { ApiEmailQueuePublisher } from './jobs/api-email-publisher.service';
83
83
  import { ApiEmailQueueSubscriber } from './jobs/api-email-subscriber.service';
84
84
  import { TestQueuePublisherDatabase } from './jobs/database/test-queue-publisher-database.service';
85
85
  import { TestQueueSubscriberDatabase } from './jobs/database/test-queue-subscriber-database.service';
86
- import { SmtpEmailQueuePublisherRabbitmq } from './jobs/smtp-email-publisher.service';
87
- import { SmtpEmailQueueSubscriberRabbitmq } from './jobs/smtp-email-subscriber.service';
86
+ import { Msg91WhatsappQueuePublisher } from './jobs/msg91-whatsapp-publisher.service';
87
+ import { Msg91WhatsappQueueSubscriber } from './jobs/msg91-whatsapp-subscriber.service';
88
88
  import { OTPQueuePublisher } from './jobs/otp-publisher.service';
89
89
  import { OTPQueueSubscriber } from './jobs/otp-subscriber.service';
90
90
  import { SmsQueuePublisher } from './jobs/sms-publisher.service';
91
91
  import { SmsQueueSubscriber } from './jobs/sms-subscriber.service';
92
+ import { SmtpEmailQueuePublisherRabbitmq } from './jobs/smtp-email-publisher.service';
93
+ import { SmtpEmailQueueSubscriberRabbitmq } from './jobs/smtp-email-subscriber.service';
92
94
  import { TestQueuePublisher } from './jobs/test-queue-publisher.service';
93
95
  import { TestQueueSubscriber } from './jobs/test-queue-subscriber.service';
94
- import { Msg91WhatsappQueuePublisher } from './jobs/msg91-whatsapp-publisher.service';
95
- import { Msg91WhatsappQueueSubscriber } from './jobs/msg91-whatsapp-subscriber.service';
96
96
  import { UserRegistrationListener } from './listeners/user-registration.listener';
97
97
  import { GoogleOauthStrategy } from './passport-strategies/google-oauth.strategy';
98
98
  import { LocalStrategy } from './passport-strategies/local.strategy';
@@ -175,36 +175,61 @@ import { ApiEmailQueuePublisherDatabase } from './jobs/database/api-email-publis
175
175
  import { ApiEmailQueueSubscriberDatabase } from './jobs/database/api-email-subscriber-database.service';
176
176
  import { ComputedFieldEvaluationPublisherDatabase } from './jobs/database/computed-field-evaluation-publisher-database.service';
177
177
  import { ComputedFieldEvaluationSubscriberDatabase } from './jobs/database/computed-field-evaluation-subscriber-database.service';
178
- import { SmtpEmailQueuePublisherDatabase } from './jobs/database/smtp-email-publisher-database.service';
179
- import { SmtpEmailQueueSubscriberDatabase } from './jobs/database/smtp-email-subscriber-database.service';
180
178
  import { GenerateCodePublisherDatabase } from './jobs/database/generate-code-publisher-database.service';
181
179
  import { GenerateCodeSubscriberDatabase } from './jobs/database/generate-code-subscriber-database.service';
182
180
  import { OTPQueuePublisherDatabase } from './jobs/database/otp-publisher-database.service';
183
181
  import { OTPQueueSubscriberDatabase } from './jobs/database/otp-subscriber-database.service';
184
182
  import { SmsQueuePublisherDatabase } from './jobs/database/sms-publisher-database.service';
185
183
  import { SmsQueueSubscriberDatabase } from './jobs/database/sms-subscriber-database.service';
184
+ import { SmtpEmailQueuePublisherDatabase } from './jobs/database/smtp-email-publisher-database.service';
185
+ import { SmtpEmailQueueSubscriberDatabase } from './jobs/database/smtp-email-subscriber-database.service';
186
186
 
187
187
  import { TwilioSmsQueuePublisherDatabase } from './jobs/database/twilio-sms-publisher-database.service';
188
188
  import { TwilioSmsQueueSubscriberDatabase } from './jobs/database/twilio-sms-subscriber-database.service';
189
189
 
190
190
 
191
- import { TriggerMcpClientPublisherDatabase } from './jobs/database/trigger-mcp-client-publisher-database.service';
192
- import { TriggerMcpClientSubscriberDatabase } from './jobs/database/trigger-mcp-client-subscriber-database.service';
191
+ import { ThrottlerModule } from '@nestjs/throttler';
192
+ import { IngestCommand } from './commands/ingest.command';
193
+ import { MailFactory } from './factories/mail.factory';
194
+ import { ErrorMapperService } from './helpers/error-mapper.service';
195
+ import { SolidCoreErrorCodesProvider } from './helpers/solid-core-error-codes-provider.service';
196
+ import { ComputedFieldEvaluationPublisherRabbitmq } from './jobs/computed-field-evaluation-publisher.service';
197
+ import { ComputedFieldEvaluationSubscriberRabbitmq } from './jobs/computed-field-evaluation-subscriber.service';
193
198
  import { Msg91WhatsappQueuePublisherDatabase } from './jobs/database/msg91-whatsapp-publisher-database.service';
194
199
  import { Msg91WhatsappQueueSubscriberDatabase } from './jobs/database/msg91-whatsapp-subscriber-database.service';
200
+ import { Three60WhatsappQueuePublisherDatabase } from './jobs/database/three60-whatsapp-publisher-database.service';
201
+ import { Three60WhatsappQueueSubscriberDatabase } from './jobs/database/three60-whatsapp-subscriber-database.service';
202
+ import { TriggerMcpClientPublisherDatabase } from './jobs/database/trigger-mcp-client-publisher-database.service';
203
+ import { TriggerMcpClientSubscriberDatabase } from './jobs/database/trigger-mcp-client-subscriber-database.service';
204
+ import { GenerateCodePublisherRabbitmq } from './jobs/generate-code-publisher.service';
205
+ import { GenerateCodeSubscriberRabbitmq } from './jobs/generate-code-subscriber.service';
206
+ import { Three60WhatsappQueuePublisher } from './jobs/three60-whatsapp-publisher.service';
207
+ import { Three60WhatsappQueueSubscriber } from './jobs/three60-whatsapp-subscriber.service';
208
+ import { TriggerMcpClientPublisherRabbitmq } from './jobs/trigger-mcp-client-publisher.service';
209
+ import { TriggerMcpClientSubscriberRabbitmq } from './jobs/trigger-mcp-client-subscriber.service';
210
+ import { TwilioSmsQueuePublisherRabbitmq } from './jobs/twilio-sms-publisher.service';
211
+ import { TwilioSmsQueueSubscriberRabbitmq } from './jobs/twilio-sms-subscriber.service';
195
212
  import { DashboardMapper } from './mappers/dashboard-mapper';
213
+ import { ListOfValuesMapper } from './mappers/list-of-values-mapper';
214
+ import { ChatterMessageDetailsRepository } from './repository/chatter-message-details.repository';
215
+ import { ChatterMessageRepository } from './repository/chatter-message.repository';
196
216
  import { DashboardRepository } from './repository/dashboard.repository';
197
217
  import { FieldMetadataRepository } from './repository/field-metadata.repository';
198
218
  import { FieldRepository } from './repository/field.repository';
199
219
  import { MediaRepository } from './repository/media.repository';
220
+ import { ScheduledJobRepository } from './repository/scheduled-job.repository';
200
221
  import { SecurityRuleRepository } from './repository/security-rule.repository';
222
+ import { UserRepository } from './repository/user.repository';
223
+ import { ViewMetadataRepository } from './repository/view-metadata.repository';
201
224
  import { PermissionMetadataSeederService } from './seeders/permission-metadata-seeder.service';
202
225
  import { SystemFieldsSeederService } from './seeders/system-fields-seeder.service';
203
226
  import { AiInteractionService } from './services/ai-interaction.service';
204
227
  import { ChatterMessageDetailsService } from './services/chatter-message-details.service';
205
228
  import { ChatterMessageService } from './services/chatter-message.service';
206
229
  import { ConcatComputedFieldProvider } from './services/computed-fields/concat-computed-field-provider.service';
230
+ import { AlphaNumExternalIdComputationProvider } from './services/computed-fields/entity/alpha-num-external-id-computed-field-provider';
207
231
  import { ConcatEntityComputedFieldProvider } from './services/computed-fields/entity/concat-entity-computed-field-provider.service';
232
+ import { NoopsEntityComputedFieldProviderService } from './services/computed-fields/entity/noops-entity-computed-field-provider.service';
208
233
  import { CRUDService } from './services/crud.service';
209
234
  import { CsvService } from './services/csv.service';
210
235
  import { DashboardQuestionSqlDatasetConfigService } from './services/dashboard-question-sql-dataset-config.service';
@@ -216,16 +241,24 @@ import { DashboardService } from './services/dashboard.service';
216
241
  import { ExcelService } from './services/excel.service';
217
242
  import { ExportTemplateService } from './services/export-template.service';
218
243
  import { ExportTransactionService } from './services/export-transaction.service';
244
+ import { IngestMetadataService } from './services/genai/ingest-metadata.service';
245
+ import { R2RHelperService } from './services/genai/r2r-helper.service';
219
246
  import { ImportTransactionErrorLogService } from './services/import-transaction-error-log.service';
220
247
  import { ImportTransactionService } from './services/import-transaction.service';
248
+ import { ListOfValuesMetadataService } from './services/list-of-values-metadata.service';
221
249
  import { LocaleService } from './services/locale.service';
222
250
  import { McpToolResponseHandlerFactory } from './services/mcp-tool-response-handlers/mcp-tool-response-handler-factory.service';
251
+ import { SolidAddFieldMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-add-field-mcp-tool-response-handler.service';
223
252
  import { SolidCreateDashboardMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-dashboard-mcp-tool-response-handler.service';
224
253
  import { SolidCreateDashboardQuestionMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-dashboard-question-mcp-tool-response-handler.service';
225
254
  import { SolidCreateDashboardQuestionSqlDatasetConfigMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-dashboard-question-sql-dataset-config-mcp-tool-response-handler.service';
255
+ import { SolidCreateDashboardWidgetMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-dashboard-widget-mcp-tool-response-handler.service';
256
+ import { SolidCreateModelWithFieldsMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-model-with-fields-mcp-tool-response-handler.service';
226
257
  import { SolidCreateModuleMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-module-mcp-tool-response-handler.service';
258
+ import { SolidCreateModelLayoutMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-save-model-layout-mcp-tool-response-handler.service';
227
259
  import { FileS3StorageProvider } from './services/mediaStorageProviders/file-s3-storage-provider';
228
260
  import { FileStorageProvider } from './services/mediaStorageProviders/file-storage-provider';
261
+ import { PollerService } from './services/poller.service';
229
262
  import { ChartJsSqlDataProvider } from './services/question-data-providers/chartjs-sql-data-provider.service';
230
263
  import { PrimeReactDatatableSqlDataProvider } from './services/question-data-providers/prime-react-datatable-sql-data-provider.service';
231
264
  import { PrimeReactMeterGroupSqlDataProvider } from './services/question-data-providers/prime-react-meter-group-sql-data-provider.service';
@@ -241,10 +274,13 @@ import { ListOfDashboardVariableProvidersSelectionProvider } from './services/se
241
274
  import { ListOfScheduledJobsSelectionProvider } from './services/selection-providers/list-of-scheduled-jobs-selection-provider.service';
242
275
  import { LocaleListSelectionProvider } from './services/selection-providers/locale-list-selection-provider.service';
243
276
  import { SettingService } from './services/setting.service';
277
+ import { TwilioSMSService } from './services/sms/TwilioSMSService';
244
278
  import { SqlExpressionResolverService } from './services/sql-expression-resolver.service';
279
+ import { TextractService } from './services/textract.service';
245
280
  import { UserActivityHistoryService } from './services/user-activity-history.service';
246
281
  import { UserViewMetadataService } from './services/user-view-metadata.service';
247
282
  import { UserService } from './services/user.service';
283
+ import { Three60WhatsappService } from './services/whatsapp/Three60WhatsappService';
248
284
  import { AuditSubscriber } from './subscribers/audit.subscriber';
249
285
  import { ComputedEntityFieldSubscriber } from './subscribers/computed-entity-field.subscriber';
250
286
  import { CreatedByUpdatedBySubscriber } from './subscribers/created-by-updated-by.subscriber';
@@ -252,48 +288,10 @@ import { DashboardQuestionSqlDatasetConfigSubscriber } from './subscribers/dashb
252
288
  import { DashboardQuestionSubscriber } from './subscribers/dashboard-question.subscriber';
253
289
  import { DashboardVariableSubscriber } from './subscribers/dashboard-variable.subscriber';
254
290
  import { DashboardSubscriber } from './subscribers/dashboard.subscriber';
291
+ import { ListOfValuesMetadataSubscriber } from './subscribers/list-of-values-metadata.subscriber';
292
+ import { ScheduledJobSubscriber } from './subscribers/scheduled-job.subscriber';
255
293
  import { SecurityRuleSubscriber } from './subscribers/security-rule.subscriber';
256
294
  import { ViewMetadataSubsciber } from './subscribers/view-metadata.subscriber';
257
- import { SolidCreateDashboardWidgetMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-dashboard-widget-mcp-tool-response-handler.service';
258
- import { SolidCreateModelWithFieldsMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-create-model-with-fields-mcp-tool-response-handler.service';
259
- import { SolidAddFieldMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-add-field-mcp-tool-response-handler.service';
260
- import { ViewMetadataRepository } from './repository/view-metadata.repository';
261
- import { SolidCreateModelLayoutMcpToolResponseHandler } from './services/mcp-tool-response-handlers/solid-save-model-layout-mcp-tool-response-handler.service';
262
- import { NoopsEntityComputedFieldProviderService } from './services/computed-fields/entity/noops-entity-computed-field-provider.service';
263
- import { ScheduledJobRepository } from './repository/scheduled-job.repository';
264
- import { ScheduledJobSubscriber } from './subscribers/scheduled-job.subscriber';
265
- import { AlphaNumExternalIdComputationProvider } from './services/computed-fields/entity/alpha-num-external-id-computed-field-provider';
266
- import { ListOfValuesMapper } from './mappers/list-of-values-mapper';
267
- import { ListOfValuesMetadataSubscriber } from './subscribers/list-of-values-metadata.subscriber';
268
- import { ListOfValuesMetadataService } from './services/list-of-values-metadata.service';
269
- import { MailFactory } from './factories/mail.factory';
270
- import { TwilioSMSService } from './services/sms/TwilioSMSService';
271
- import { PollerService } from './services/poller.service';
272
- import { TextractService } from './services/textract.service';
273
- import { seconds, ThrottlerModule } from '@nestjs/throttler';
274
- import { ChatterMessageRepository } from './repository/chatter-message.repository';
275
- import { ChatterMessageDetailsRepository } from './repository/chatter-message-details.repository';
276
- import { Three60WhatsappQueuePublisher } from './jobs/three60-whatsapp-publisher.service';
277
- import { Three60WhatsappQueueSubscriber } from './jobs/three60-whatsapp-subscriber.service';
278
- import { Three60WhatsappQueuePublisherDatabase } from './jobs/database/three60-whatsapp-publisher-database.service';
279
- import { Three60WhatsappQueueSubscriberDatabase } from './jobs/database/three60-whatsapp-subscriber-database.service';
280
- import { Three60WhatsappService } from './services/whatsapp/Three60WhatsappService';
281
- import { ThrottlerStorageRedisService } from '@nest-lab/throttler-storage-redis/src/throttler-storage-redis.service';
282
- import { isRedisConfigured } from './helpers/environment.helper';
283
- import { UserRepository } from './repository/user.repository';
284
- import { ErrorMapperService } from './helpers/error-mapper.service';
285
- import { IngestCommand } from './commands/ingest.command';
286
- import { R2RHelperService } from './services/genai/r2r-helper.service';
287
- import { IngestMetadataService } from './services/genai/ingest-metadata.service';
288
- import { ComputedFieldEvaluationPublisherRabbitmq } from './jobs/computed-field-evaluation-publisher.service';
289
- import { ComputedFieldEvaluationSubscriberRabbitmq } from './jobs/computed-field-evaluation-subscriber.service';
290
- import { GenerateCodePublisherRabbitmq } from './jobs/generate-code-publisher.service';
291
- import { GenerateCodeSubscriberRabbitmq } from './jobs/generate-code-subscriber.service';
292
- import { TriggerMcpClientPublisherRabbitmq } from './jobs/trigger-mcp-client-publisher.service';
293
- import { TriggerMcpClientSubscriberRabbitmq } from './jobs/trigger-mcp-client-subscriber.service';
294
- import { TwilioSmsQueuePublisherRabbitmq } from './jobs/twilio-sms-publisher.service';
295
- import { TwilioSmsQueueSubscriberRabbitmq } from './jobs/twilio-sms-subscriber.service';
296
- import { SolidCoreErrorCodesProvider } from './helpers/solid-core-error-codes-provider.service';
297
295
 
298
296
 
299
297
  @Global()
@@ -368,19 +366,19 @@ import { SolidCoreErrorCodesProvider } from './helpers/solid-core-error-codes-pr
368
366
  HttpModule,
369
367
  ConfigModule,
370
368
  ClsModule,
371
- ThrottlerModule.forRootAsync({
372
- imports: [ConfigModule],
373
- inject: [ConfigService],
374
- useFactory: (configService: ConfigService) => ({
375
- throttlers: [
376
- { name: 'short', ttl: seconds(10), limit: 10 },
377
- { name: 'login', ttl: seconds(10), limit: 5 },
378
- { name: 'burst', ttl: seconds(1), limit: 100 },
379
- { name: 'sustained', ttl: seconds(300), limit: 500 },
380
- ],
381
- storage: isRedisConfigured(configService) ? new ThrottlerStorageRedisService(`redis://${configService.get<string>('REDIS_HOST')}:${configService.get<string>('REDIS_PORT')}`) : undefined,
382
- }),
383
- }),
369
+ // ThrottlerModule.forRootAsync({
370
+ // imports: [ConfigModule],
371
+ // inject: [ConfigService],
372
+ // useFactory: (configService: ConfigService) => ({
373
+ // throttlers: [
374
+ // { name: 'short', ttl: seconds(10), limit: 10 },
375
+ // { name: 'login', ttl: seconds(10), limit: 5 },
376
+ // { name: 'burst', ttl: seconds(1), limit: 100 },
377
+ // { name: 'sustained', ttl: seconds(300), limit: 500 },
378
+ // ],
379
+ // storage: isRedisConfigured(configService) ? new ThrottlerStorageRedisService(`redis://${configService.get<string>('REDIS_HOST')}:${configService.get<string>('REDIS_PORT')}`) : undefined,
380
+ // }),
381
+ // }),
384
382
  ],
385
383
  controllers: [
386
384
  ModuleMetadataController,
@@ -64,7 +64,12 @@ export class AuditSubscriber implements EntitySubscriberInterface {
64
64
  return false;
65
65
  }
66
66
 
67
- return auditFields.some(field => {
67
+ // if (!entity) {
68
+ // console.warn(`[AuditSubscriber] Skipping audit for ${metadata.name} – entity is undefined or null`);
69
+ // return false;
70
+ // }
71
+
72
+ return entity && auditFields.some(field => {
68
73
  const fieldValue = entity[field.name];
69
74
  return fieldValue !== undefined && fieldValue !== null;
70
75
  });