@solidxai/core 0.1.11-beta.8 → 0.1.11

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 (98) hide show
  1. package/CHANGELOG.md +456 -0
  2. package/dist/controllers/datasource-introspection.controller.d.ts +8 -0
  3. package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -1
  4. package/dist/controllers/media.controller.js +0 -2
  5. package/dist/controllers/media.controller.js.map +1 -1
  6. package/dist/helpers/module-metadata-helper.service.js +1 -1
  7. package/dist/helpers/module-metadata-helper.service.js.map +1 -1
  8. package/dist/helpers/solid-registry.d.ts +1 -2
  9. package/dist/helpers/solid-registry.d.ts.map +1 -1
  10. package/dist/helpers/solid-registry.js.map +1 -1
  11. package/dist/helpers/typeorm-db-helper.d.ts +1 -0
  12. package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
  13. package/dist/helpers/typeorm-db-helper.js +12 -0
  14. package/dist/helpers/typeorm-db-helper.js.map +1 -1
  15. package/dist/index.d.ts +0 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +0 -1
  18. package/dist/index.js.map +1 -1
  19. package/dist/interfaces.d.ts +1 -0
  20. package/dist/interfaces.d.ts.map +1 -1
  21. package/dist/interfaces.js.map +1 -1
  22. package/dist/seeders/seed-data/solid-core-metadata.json +62 -33
  23. package/dist/services/authentication.service.d.ts +2 -0
  24. package/dist/services/authentication.service.d.ts.map +1 -1
  25. package/dist/services/authentication.service.js +32 -11
  26. package/dist/services/authentication.service.js.map +1 -1
  27. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
  28. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +5 -6
  29. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
  30. package/dist/services/crud-helper.service.d.ts.map +1 -1
  31. package/dist/services/crud-helper.service.js +32 -12
  32. package/dist/services/crud-helper.service.js.map +1 -1
  33. package/dist/services/datasource-introspection.service.d.ts +10 -0
  34. package/dist/services/datasource-introspection.service.d.ts.map +1 -1
  35. package/dist/services/datasource-introspection.service.js +109 -17
  36. package/dist/services/datasource-introspection.service.js.map +1 -1
  37. package/dist/services/menu-item-metadata.service.d.ts.map +1 -1
  38. package/dist/services/menu-item-metadata.service.js +1 -0
  39. package/dist/services/menu-item-metadata.service.js.map +1 -1
  40. package/dist/services/model-metadata.service.d.ts +2 -0
  41. package/dist/services/model-metadata.service.d.ts.map +1 -1
  42. package/dist/services/model-metadata.service.js +49 -15
  43. package/dist/services/model-metadata.service.js.map +1 -1
  44. package/dist/services/module-metadata.service.d.ts.map +1 -1
  45. package/dist/services/module-metadata.service.js +0 -27
  46. package/dist/services/module-metadata.service.js.map +1 -1
  47. package/dist/services/settings/default-settings-provider.service.d.ts +212 -0
  48. package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
  49. package/dist/services/settings/default-settings-provider.service.js +106 -0
  50. package/dist/services/settings/default-settings-provider.service.js.map +1 -1
  51. package/dist/services/solid-ts-morph.service.d.ts +6 -0
  52. package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
  53. package/dist/services/solid-ts-morph.service.js +43 -0
  54. package/dist/services/solid-ts-morph.service.js.map +1 -1
  55. package/dist/subscribers/audit.subscriber.d.ts +0 -1
  56. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  57. package/dist/subscribers/audit.subscriber.js +1 -10
  58. package/dist/subscribers/audit.subscriber.js.map +1 -1
  59. package/dist/subscribers/computed-entity-field.subscriber.d.ts +1 -1
  60. package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
  61. package/dist/subscribers/computed-entity-field.subscriber.js +11 -13
  62. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  63. package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
  64. package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
  65. package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
  66. package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
  67. package/dist/subscribers/scheduled-job.subscriber.js +1 -1
  68. package/dist/subscribers/scheduled-job.subscriber.js.map +1 -1
  69. package/dist/subscribers/security-rule.subscriber.js +1 -1
  70. package/dist/subscribers/security-rule.subscriber.js.map +1 -1
  71. package/package.json +1 -1
  72. package/src/controllers/media.controller.ts +1 -1
  73. package/src/helpers/module-metadata-helper.service.ts +1 -1
  74. package/src/helpers/solid-registry.ts +1 -7
  75. package/src/helpers/typeorm-db-helper.ts +15 -0
  76. package/src/index.ts +0 -1
  77. package/src/interfaces.ts +1 -0
  78. package/src/seeders/seed-data/solid-core-metadata.json +62 -33
  79. package/src/services/authentication.service.ts +46 -12
  80. package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +5 -10
  81. package/src/services/crud-helper.service.ts +32 -12
  82. package/src/services/datasource-introspection.service.ts +176 -16
  83. package/src/services/menu-item-metadata.service.ts +2 -1
  84. package/src/services/model-metadata.service.ts +63 -21
  85. package/src/services/module-metadata.service.ts +0 -35
  86. package/src/services/settings/default-settings-provider.service.ts +106 -0
  87. package/src/services/solid-ts-morph.service.ts +61 -1
  88. package/src/subscribers/audit.subscriber.ts +1 -12
  89. package/src/subscribers/computed-entity-field.subscriber.ts +23 -29
  90. package/src/subscribers/created-by-updated-by.subscriber.ts +0 -3
  91. package/src/subscribers/field-metadata.subscriber.ts +0 -3
  92. package/src/subscribers/scheduled-job.subscriber.ts +1 -1
  93. package/src/subscribers/security-rule.subscriber.ts +1 -1
  94. package/dist/helpers/nodemon-heartbeat.d.ts +0 -5
  95. package/dist/helpers/nodemon-heartbeat.d.ts.map +0 -1
  96. package/dist/helpers/nodemon-heartbeat.js +0 -67
  97. package/dist/helpers/nodemon-heartbeat.js.map +0 -1
  98. package/src/helpers/nodemon-heartbeat.ts +0 -59
@@ -1 +1 @@
1
- {"version":3,"file":"scheduled-job.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/scheduled-job.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from \"fs/promises\";\nimport { CreateScheduledJobDto } from \"src/dtos/create-scheduled-job.dto\";\nimport { ModuleMetadata } from \"src/entities/module-metadata.entity\";\nimport { ScheduledJob } from \"src/entities/scheduled-job.entity\";\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { ScheduledJobRepository } from \"src/repository/scheduled-job.repository\";\nimport {\n DataSource,\n EntityManager,\n EntitySubscriberInterface,\n InsertEvent,\n RemoveEvent,\n UpdateEvent,\n} from \"typeorm\";\n\n@Injectable()\nexport class ScheduledJobSubscriber\n implements EntitySubscriberInterface<ScheduledJob> {\n private readonly logger = new Logger(ScheduledJobSubscriber.name);\n\n /** Fields that, when changed (and only these changed), should NOT trigger metadata update. */\n private readonly ignoredUpdateFields: Array<keyof ScheduledJob | string> = [\n \"lastRunAt\",\n \"nextRunAt\",\n \"updatedAt\",\n ];\n\n constructor(\n @InjectDataSource() private readonly dataSource: DataSource,\n private readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n private readonly scheduledJobRepo: ScheduledJobRepository\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return ScheduledJob;\n }\n\n async afterInsert(event: InsertEvent<ScheduledJob>) {\n if (!event.entity) {\n this.logger.debug('No schedule Job entity found in the afterInsert method');\n return;\n }\n await this.updateMetadata(event.entity, event.queryRunner.manager);\n }\n\n async afterUpdate(event: UpdateEvent<ScheduledJob>) {\n if (!event.databaseEntity) {\n this.logger.debug('No schedule Job entity found in the afterUpdate method');\n return;\n }\n\n // get hold of the changed field names \n const changedProps = (event.updatedColumns ?? []).map((c) => c.propertyName);\n\n // Decide whether to skip: only skip when *all* changed fields are in the ignore list\n const onlyIgnoredChanged = changedProps.every((p) => this.ignoredUpdateFields.includes(p));\n\n if (onlyIgnoredChanged) {\n this.logger.debug(`Skipping metadata update for ScheduledJob#${(event.databaseEntity as ScheduledJob).id}; only ignored fields changed: ${changedProps.join(\", \")}`\n );\n return;\n }\n\n await this.updateMetadata(event.databaseEntity, event.queryRunner.manager);\n }\n\n async afterRemove(event: RemoveEvent<ScheduledJob>) {\n await this.removeMetadata(event);\n }\n\n private async removeMetadata(event: RemoveEvent<ScheduledJob>) {\n const jobEntity = event.entity;\n const moduleMetadata = jobEntity?.module;\n\n if (!moduleMetadata) {\n this.logger.error(\n `Module metadata not found for scheduled job with ID ${jobEntity?.id}`\n );\n return;\n }\n\n const moduleMetadataRepo = event.queryRunner.manager.getRepository(ModuleMetadata);\n const populatedModuleMetadata = await moduleMetadataRepo.findOne({\n where: { id: moduleMetadata.id },\n });\n\n if (!populatedModuleMetadata) {\n this.logger.error(\n `Could not find ModuleMetadata with ID ${moduleMetadata.id}`\n );\n return;\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedModuleMetadata.name\n );\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n if (existingIndex !== -1) {\n metaData.scheduledJobs.splice(existingIndex, 1);\n this.logger.log(`Removed scheduled job ${jobName} from metadata`);\n }\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n\n private async updateMetadata(jobEntity: ScheduledJob, entityManager: EntityManager) {\n // populate the job with its relation\n const populatedScheduleJob = await entityManager.findOne(ScheduledJob, {\n where: { id: jobEntity.id },\n relations: ['module'],\n });\n\n if (!populatedScheduleJob) {\n throw new Error(`ScheduleJob not found for id ${jobEntity.id}`);\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedScheduleJob.module?.name\n );\n\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n\n // Ensure scheduledJobs exists\n if (!metaData.scheduledJobs) {\n metaData.scheduledJobs = [];\n }\n\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n // Insert or update job in metadata\n const jobDto: CreateScheduledJobDto = await this.scheduledJobRepo.toDto(populatedScheduleJob as ScheduledJob);\n // Strip out bookkeeping/runtime fields before persisting to metadata JSON.\n const {\n moduleId,\n lastRunAt,\n nextRunAt,\n ...dtoToWrite\n } = jobDto;\n if (existingIndex !== -1) {\n metaData.scheduledJobs[existingIndex] = dtoToWrite;\n this.logger.log(`Updated scheduled job ${jobName} in metadata`);\n } else {\n metaData.scheduledJobs.push(dtoToWrite);\n this.logger.log(`Added scheduled job ${jobName} to metadata`);\n }\n\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n}\n"]}
1
+ {"version":3,"file":"scheduled-job.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/scheduled-job.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from \"fs/promises\";\nimport { CreateScheduledJobDto } from \"src/dtos/create-scheduled-job.dto\";\nimport { ModuleMetadata } from \"src/entities/module-metadata.entity\";\nimport { ScheduledJob } from \"src/entities/scheduled-job.entity\";\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { ScheduledJobRepository } from \"src/repository/scheduled-job.repository\";\nimport {\n DataSource,\n EntityManager,\n EntitySubscriberInterface,\n InsertEvent,\n RemoveEvent,\n UpdateEvent,\n} from \"typeorm\";\n\n@Injectable()\nexport class ScheduledJobSubscriber\n implements EntitySubscriberInterface<ScheduledJob> {\n private readonly logger = new Logger(ScheduledJobSubscriber.name);\n\n /** Fields that, when changed (and only these changed), should NOT trigger metadata update. */\n private readonly ignoredUpdateFields: Array<keyof ScheduledJob | string> = [\n \"lastRunAt\",\n \"nextRunAt\",\n \"updatedAt\",\n ];\n\n constructor(\n @InjectDataSource() private readonly dataSource: DataSource,\n private readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n private readonly scheduledJobRepo: ScheduledJobRepository\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return ScheduledJob;\n }\n\n async afterInsert(event: InsertEvent<ScheduledJob>) {\n if (!event.entity) {\n this.logger.debug('No schedule Job entity found in the afterInsert method');\n return;\n }\n await this.updateMetadata(event.entity, event.queryRunner.manager);\n }\n\n async afterUpdate(event: UpdateEvent<ScheduledJob>) {\n if (!event.databaseEntity) {\n this.logger.debug('No schedule Job entity found in the afterUpdate method');\n return;\n }\n\n // get hold of the changed field names \n const changedProps = (event.updatedColumns ?? []).map((c) => c.propertyName);\n\n // Decide whether to skip: only skip when *all* changed fields are in the ignore list\n const onlyIgnoredChanged = changedProps.every((p) => this.ignoredUpdateFields.includes(p));\n\n if (onlyIgnoredChanged) {\n this.logger.debug(`Skipping metadata update for ScheduledJob#${(event.databaseEntity as ScheduledJob).id}; only ignored fields changed: ${changedProps.join(\", \")}`\n );\n return;\n }\n\n await this.updateMetadata(event.databaseEntity, event.queryRunner.manager);\n }\n\n async afterRemove(event: RemoveEvent<ScheduledJob>) {\n await this.removeMetadata(event);\n }\n\n private async removeMetadata(event: RemoveEvent<ScheduledJob>) {\n const jobEntity = event.entity;\n const moduleMetadata = jobEntity?.module;\n\n if (!moduleMetadata) {\n this.logger.error(\n `Module metadata not found for scheduled job with ID ${jobEntity?.id}`\n );\n return;\n }\n\n const moduleMetadataRepo = this.dataSource.getRepository(ModuleMetadata);\n const populatedModuleMetadata = await moduleMetadataRepo.findOne({\n where: { id: moduleMetadata.id },\n });\n\n if (!populatedModuleMetadata) {\n this.logger.error(\n `Could not find ModuleMetadata with ID ${moduleMetadata.id}`\n );\n return;\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedModuleMetadata.name\n );\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n if (existingIndex !== -1) {\n metaData.scheduledJobs.splice(existingIndex, 1);\n this.logger.log(`Removed scheduled job ${jobName} from metadata`);\n }\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n\n private async updateMetadata(jobEntity: ScheduledJob, entityManager: EntityManager) {\n // populate the job with its relation\n const populatedScheduleJob = await entityManager.findOne(ScheduledJob, {\n where: { id: jobEntity.id },\n relations: ['module'],\n });\n\n if (!populatedScheduleJob) {\n throw new Error(`ScheduleJob not found for id ${jobEntity.id}`);\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedScheduleJob.module?.name\n );\n\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n\n // Ensure scheduledJobs exists\n if (!metaData.scheduledJobs) {\n metaData.scheduledJobs = [];\n }\n\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n // Insert or update job in metadata\n const jobDto: CreateScheduledJobDto = await this.scheduledJobRepo.toDto(populatedScheduleJob as ScheduledJob);\n // Strip out bookkeeping/runtime fields before persisting to metadata JSON.\n const {\n moduleId,\n lastRunAt,\n nextRunAt,\n ...dtoToWrite\n } = jobDto;\n if (existingIndex !== -1) {\n metaData.scheduledJobs[existingIndex] = dtoToWrite;\n this.logger.log(`Updated scheduled job ${jobName} in metadata`);\n } else {\n metaData.scheduledJobs.push(dtoToWrite);\n this.logger.log(`Added scheduled job ${jobName} to metadata`);\n }\n\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n}\n"]}
@@ -80,7 +80,7 @@ let SecurityRuleSubscriber = SecurityRuleSubscriber_1 = class SecurityRuleSubscr
80
80
  this.logger.error(`Model metadata not found for security rule with id ${event.entity.id}`);
81
81
  return;
82
82
  }
83
- const modelMetadataRepo = event.manager.getRepository(model_metadata_entity_1.ModelMetadata);
83
+ const modelMetadataRepo = this.dataSource.getRepository(model_metadata_entity_1.ModelMetadata);
84
84
  const populatedModelMetadata = await modelMetadataRepo.findOne({
85
85
  where: {
86
86
  id: modelMetadata.id
@@ -1 +1 @@
1
- {"version":3,"file":"security-rule.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/security-rule.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await\nimport { SOLID_CORE_MODULE_NAME } from 'src/constants';\nimport { ModelMetadata } from 'src/entities/model-metadata.entity';\nimport { SecurityRule } from 'src/entities/security-rule.entity';\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { SecurityRuleRepository } from 'src/repository/security-rule.repository';\nimport { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from \"typeorm\";\n\n@Injectable()\nexport class SecurityRuleSubscriber implements EntitySubscriberInterface<SecurityRule> {\n private readonly logger = new Logger(SecurityRuleSubscriber.name);\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n readonly securityRuleRepo: SecurityRuleRepository,\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return SecurityRule;\n }\n\n async afterInsert(event: InsertEvent<SecurityRule>) {\n await this.saveSecurityRules(event);\n }\n\n async afterUpdate(event: UpdateEvent<SecurityRule>) {\n await this.saveSecurityRules(event);\n }\n\n async saveSecurityRules(event: UpdateEvent<SecurityRule> | InsertEvent<SecurityRule>) {\n const securityRule = event.entity as SecurityRule;\n const modelMetadata = event.entity.modelMetadata;\n if (!modelMetadata) {\n this.logger.error(`Model metadata not found for security rule with id ${event.entity.id}`);\n return;\n }\n\n const modelMetadataRepo = event.manager.getRepository(ModelMetadata);\n const populatedModelMetadata = await modelMetadataRepo.findOne({\n where: {\n id: modelMetadata.id\n },\n relations: {\n module: true,\n }\n });\n\n // Ignore further processing if the module is solid core module, since solid core security rules cannot be seeded from the UI\n if (populatedModelMetadata.module.name === SOLID_CORE_MODULE_NAME) {\n return;\n }\n\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(populatedModelMetadata.module.name);\n try {\n await fs.access(filePath);\n } catch (error: any) {\n // FIXME - Should we actually delete the security rule here, if the file is not found?\n this.logger.error(`File not found at path: ${filePath}`);\n return;\n }\n const metaData = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(filePath);\n\n if (metaData.securityRules) {\n const securityRuleIndex = metaData.securityRules?.findIndex((ruleFromFile: { name: string }) => ruleFromFile.name === securityRule.name);\n const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule)\n metaData.securityRules[securityRuleIndex] = { ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) }\n }\n else {\n const securityRules = []\n const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule)\n securityRules.push({ ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) })\n metaData.securityRules = securityRules\n }\n // Write the updated object back to the file\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n }\n\n}"]}
1
+ {"version":3,"file":"security-rule.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/security-rule.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await\nimport { SOLID_CORE_MODULE_NAME } from 'src/constants';\nimport { ModelMetadata } from 'src/entities/model-metadata.entity';\nimport { SecurityRule } from 'src/entities/security-rule.entity';\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { SecurityRuleRepository } from 'src/repository/security-rule.repository';\nimport { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from \"typeorm\";\n\n@Injectable()\nexport class SecurityRuleSubscriber implements EntitySubscriberInterface<SecurityRule> {\n private readonly logger = new Logger(SecurityRuleSubscriber.name);\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n readonly securityRuleRepo: SecurityRuleRepository,\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return SecurityRule;\n }\n\n async afterInsert(event: InsertEvent<SecurityRule>) {\n await this.saveSecurityRules(event);\n }\n\n async afterUpdate(event: UpdateEvent<SecurityRule>) {\n await this.saveSecurityRules(event);\n }\n\n async saveSecurityRules(event: UpdateEvent<SecurityRule> | InsertEvent<SecurityRule>) {\n const securityRule = event.entity as SecurityRule;\n const modelMetadata = event.entity.modelMetadata;\n if (!modelMetadata) {\n this.logger.error(`Model metadata not found for security rule with id ${event.entity.id}`);\n return;\n }\n\n const modelMetadataRepo = this.dataSource.getRepository(ModelMetadata);\n const populatedModelMetadata = await modelMetadataRepo.findOne({\n where: {\n id: modelMetadata.id\n },\n relations: {\n module: true,\n }\n });\n\n // Ignore further processing if the module is solid core module, since solid core security rules cannot be seeded from the UI\n if (populatedModelMetadata.module.name === SOLID_CORE_MODULE_NAME) {\n return;\n }\n\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(populatedModelMetadata.module.name);\n try {\n await fs.access(filePath);\n } catch (error: any) {\n // FIXME - Should we actually delete the security rule here, if the file is not found?\n this.logger.error(`File not found at path: ${filePath}`);\n return;\n }\n const metaData = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(filePath);\n\n if (metaData.securityRules) {\n const securityRuleIndex = metaData.securityRules?.findIndex((ruleFromFile: { name: string }) => ruleFromFile.name === securityRule.name);\n const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule)\n metaData.securityRules[securityRuleIndex] = { ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) }\n }\n else {\n const securityRules = []\n const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule)\n securityRules.push({ ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) })\n metaData.securityRules = securityRules\n }\n // Write the updated object back to the file\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n }\n\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidxai/core",
3
- "version": "0.1.11-beta.8",
3
+ "version": "0.1.11",
4
4
  "description": "This module is a NestJS module containing all the required core providers required by a Solid application",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -47,7 +47,7 @@ export class MediaController {
47
47
  return this.service.update(id, updateDto, files, true);
48
48
  }
49
49
 
50
- @Public()
50
+ // @Public()
51
51
  // @SkipThrottle({ short: false, login: true, burst: true, sustained: true }) //Enable the short throttle only
52
52
  @ApiBearerAuth("jwt")
53
53
  @Post('/upload')
@@ -34,7 +34,7 @@ export class ModuleMetadataHelperService {
34
34
  if (!moduleName) {
35
35
  return '';
36
36
  }
37
- return path.resolve(process.cwd(), 'src', moduleName);
37
+ return path.resolve(process.cwd(), 'src', kebabCase(moduleName));
38
38
  }
39
39
 
40
40
  async getSolidUiModulePath(moduleName: string): Promise<string> {
@@ -8,7 +8,7 @@ import { Locale } from 'src/entities/locale.entity';
8
8
  import { SecurityRule } from 'src/entities/security-rule.entity';
9
9
  import { IScheduledJob } from 'src/services/scheduled-jobs/scheduled-job.interface';
10
10
  import { IDashboardWidgetDataProvider, IErrorCodeProvider, ISecurityRuleConfigProvider, ISelectionProvider, ISelectionProviderContext, ISolidDatabaseModule } from "../interfaces";
11
- import { EntityManager, ObjectLiteral } from 'typeorm';
11
+ import { ObjectLiteral } from 'typeorm';
12
12
 
13
13
  type ControllerMetadata = {
14
14
  name: string;
@@ -49,12 +49,6 @@ export interface TypeOrmEventContext {
49
49
  metadataName?: string;
50
50
  updatedColumns?: string[];
51
51
  updatedRelations?: string[];
52
- // Transaction-bound EntityManager from the originating TypeORM event. Providers that
53
- // need to query the DB during a pre-compute hook must use this (not an injected
54
- // DataSource/EntityManager) so the query runs on the active transaction's connection.
55
- // On single-threaded embedded engines (PGlite), a second connection mid-transaction
56
- // can deadlock.
57
- manager?: EntityManager;
58
52
  }
59
53
 
60
54
  export interface ComputedFieldMetadata<TContext = any> {
@@ -45,6 +45,21 @@ const solidCoreDbType: DatasourceType =
45
45
  ? (process.env.SOLID_CORE_DB_TYPE as DatasourceType)
46
46
  : DatasourceType.postgres;
47
47
 
48
+ // Must use ANSI CAST() syntax — not Postgres-specific `::text` — because TypeORM's
49
+ // replacePropertyNamesForTheWholeQuery regex treats ':' as part of the property name,
50
+ // so `alias.col::text` is parsed as property `col::text` (no match → no column substitution).
51
+ export function buildCastToText(driver: string, colExpr: string): string {
52
+ switch (driver) {
53
+ case DatasourceType.mssql:
54
+ return `CAST(${colExpr} AS NVARCHAR(MAX))`;
55
+ case DatasourceType.mysql:
56
+ case DatasourceType.mariadb:
57
+ return `CAST(${colExpr} AS CHAR)`;
58
+ default:
59
+ return `CAST(${colExpr} AS TEXT)`;
60
+ }
61
+ }
62
+
48
63
  export function getColumnType(solidType: string): ColumnOptions {
49
64
  switch (solidType) {
50
65
  case "longText":
package/src/index.ts CHANGED
@@ -171,7 +171,6 @@ export * from './guards/permissions.guard'
171
171
  export * from './guards/roles.guard'
172
172
 
173
173
  export * from './helpers/command.service'
174
- export * from './helpers/nodemon-heartbeat'
175
174
  export * from './helpers/module.helper'
176
175
  export * from './helpers/schematic.service'
177
176
  export * from './helpers/solid-registry'
package/src/interfaces.ts CHANGED
@@ -89,6 +89,7 @@ export interface SettingDefinition<T = any> {
89
89
  encrypted?: boolean;
90
90
  label?: string;
91
91
  description?: string;
92
+ helpText?: string;
92
93
  placeholder?: string;
93
94
  group?: string;
94
95
  sortOrder?: number;
@@ -6116,7 +6116,8 @@
6116
6116
  "sequenceNumber": 1,
6117
6117
  "actionUserKey": "moduleMetadata-list-action",
6118
6118
  "moduleUserKey": "solid-core",
6119
- "parentMenuItemUserKey": "appBuilder-menu-item"
6119
+ "parentMenuItemUserKey": "appBuilder-menu-item",
6120
+ "iconName": "view_module"
6120
6121
  },
6121
6122
  {
6122
6123
  "displayName": "Model",
@@ -6124,7 +6125,8 @@
6124
6125
  "sequenceNumber": 2,
6125
6126
  "actionUserKey": "modelMetadata-list-action",
6126
6127
  "moduleUserKey": "solid-core",
6127
- "parentMenuItemUserKey": "appBuilder-menu-item"
6128
+ "parentMenuItemUserKey": "appBuilder-menu-item",
6129
+ "iconName": "table_rows"
6128
6130
  },
6129
6131
  {
6130
6132
  "displayName": "Field",
@@ -6132,7 +6134,8 @@
6132
6134
  "sequenceNumber": 3,
6133
6135
  "actionUserKey": "fieldMetadata-list-action",
6134
6136
  "moduleUserKey": "solid-core",
6135
- "parentMenuItemUserKey": "appBuilder-menu-item"
6137
+ "parentMenuItemUserKey": "appBuilder-menu-item",
6138
+ "iconName": "label"
6136
6139
  },
6137
6140
  {
6138
6141
  "displayName": "Datasources",
@@ -6140,7 +6143,8 @@
6140
6143
  "sequenceNumber": 4,
6141
6144
  "actionUserKey": "datasource-management-action",
6142
6145
  "moduleUserKey": "solid-core",
6143
- "parentMenuItemUserKey": "appBuilder-menu-item"
6146
+ "parentMenuItemUserKey": "appBuilder-menu-item",
6147
+ "iconName": "storage"
6144
6148
  },
6145
6149
  {
6146
6150
  "displayName": "Menu Item",
@@ -6148,7 +6152,8 @@
6148
6152
  "sequenceNumber": 1,
6149
6153
  "actionUserKey": "menuItemMetadata-list-action",
6150
6154
  "moduleUserKey": "solid-core",
6151
- "parentMenuItemUserKey": "layoutBuilder-menu-item"
6155
+ "parentMenuItemUserKey": "layoutBuilder-menu-item",
6156
+ "iconName": "menu"
6152
6157
  },
6153
6158
  {
6154
6159
  "displayName": "View",
@@ -6156,7 +6161,8 @@
6156
6161
  "sequenceNumber": 2,
6157
6162
  "actionUserKey": "viewMetadata-list-action",
6158
6163
  "moduleUserKey": "solid-core",
6159
- "parentMenuItemUserKey": "layoutBuilder-menu-item"
6164
+ "parentMenuItemUserKey": "layoutBuilder-menu-item",
6165
+ "iconName": "pageview"
6160
6166
  },
6161
6167
  {
6162
6168
  "displayName": "Action",
@@ -6164,7 +6170,8 @@
6164
6170
  "sequenceNumber": 3,
6165
6171
  "actionUserKey": "actionMetadata-list-action",
6166
6172
  "moduleUserKey": "solid-core",
6167
- "parentMenuItemUserKey": "layoutBuilder-menu-item"
6173
+ "parentMenuItemUserKey": "layoutBuilder-menu-item",
6174
+ "iconName": "bolt"
6168
6175
  },
6169
6176
  {
6170
6177
  "displayName": "User View",
@@ -6172,7 +6179,8 @@
6172
6179
  "sequenceNumber": 5,
6173
6180
  "actionUserKey": "userViewMetadata-list-action",
6174
6181
  "moduleUserKey": "solid-core",
6175
- "parentMenuItemUserKey": "layoutBuilder-menu-item"
6182
+ "parentMenuItemUserKey": "layoutBuilder-menu-item",
6183
+ "iconName": "person"
6176
6184
  },
6177
6185
  {
6178
6186
  "displayName": "Media Management",
@@ -6189,7 +6197,8 @@
6189
6197
  "sequenceNumber": 1,
6190
6198
  "actionUserKey": "media-list-action",
6191
6199
  "moduleUserKey": "solid-core",
6192
- "parentMenuItemUserKey": "mediaManagement-menu-item"
6200
+ "parentMenuItemUserKey": "mediaManagement-menu-item",
6201
+ "iconName": "perm_media"
6193
6202
  },
6194
6203
  {
6195
6204
  "displayName": "Media Storage Provider",
@@ -6197,7 +6206,8 @@
6197
6206
  "sequenceNumber": 2,
6198
6207
  "actionUserKey": "mediaStorageProviderMetadata-list-action",
6199
6208
  "moduleUserKey": "solid-core",
6200
- "parentMenuItemUserKey": "mediaManagement-menu-item"
6209
+ "parentMenuItemUserKey": "mediaManagement-menu-item",
6210
+ "iconName": "cloud"
6201
6211
  },
6202
6212
  {
6203
6213
  "displayName": "IAM",
@@ -6206,7 +6216,7 @@
6206
6216
  "actionUserKey": "",
6207
6217
  "moduleUserKey": "solid-core",
6208
6218
  "parentMenuItemUserKey": "",
6209
- "iconName": "person_shield"
6219
+ "iconName": "manage_accounts"
6210
6220
  },
6211
6221
  {
6212
6222
  "displayName": "User",
@@ -6214,7 +6224,8 @@
6214
6224
  "sequenceNumber": 1,
6215
6225
  "actionUserKey": "user-list-action",
6216
6226
  "moduleUserKey": "solid-core",
6217
- "parentMenuItemUserKey": "iam-menu-item"
6227
+ "parentMenuItemUserKey": "iam-menu-item",
6228
+ "iconName": "person"
6218
6229
  },
6219
6230
  {
6220
6231
  "displayName": "Role",
@@ -6222,7 +6233,8 @@
6222
6233
  "sequenceNumber": 2,
6223
6234
  "actionUserKey": "roleMetadata-list-action",
6224
6235
  "moduleUserKey": "solid-core",
6225
- "parentMenuItemUserKey": "iam-menu-item"
6236
+ "parentMenuItemUserKey": "iam-menu-item",
6237
+ "iconName": "admin_panel_settings"
6226
6238
  },
6227
6239
  {
6228
6240
  "displayName": "Permission",
@@ -6230,7 +6242,8 @@
6230
6242
  "sequenceNumber": 3,
6231
6243
  "actionUserKey": "permissionMetadata-list-action",
6232
6244
  "moduleUserKey": "solid-core",
6233
- "parentMenuItemUserKey": "iam-menu-item"
6245
+ "parentMenuItemUserKey": "iam-menu-item",
6246
+ "iconName": "key"
6234
6247
  },
6235
6248
  {
6236
6249
  "displayName": "Security rules",
@@ -6238,7 +6251,8 @@
6238
6251
  "sequenceNumber": 4,
6239
6252
  "actionUserKey": "securityRule-list-action",
6240
6253
  "moduleUserKey": "solid-core",
6241
- "parentMenuItemUserKey": "iam-menu-item"
6254
+ "parentMenuItemUserKey": "iam-menu-item",
6255
+ "iconName": "gavel"
6242
6256
  },
6243
6257
  {
6244
6258
  "displayName": "User Activity History",
@@ -6246,7 +6260,8 @@
6246
6260
  "sequenceNumber": 5,
6247
6261
  "actionUserKey": "userActivityHistory-list-action",
6248
6262
  "moduleUserKey": "solid-core",
6249
- "parentMenuItemUserKey": "iam-menu-item"
6263
+ "parentMenuItemUserKey": "iam-menu-item",
6264
+ "iconName": "history"
6250
6265
  },
6251
6266
  {
6252
6267
  "displayName": "Queues",
@@ -6263,7 +6278,8 @@
6263
6278
  "sequenceNumber": 1,
6264
6279
  "actionUserKey": "solid-core-queue-health-dashboard-action",
6265
6280
  "moduleUserKey": "solid-core",
6266
- "parentMenuItemUserKey": "queues-menu-item"
6281
+ "parentMenuItemUserKey": "queues-menu-item",
6282
+ "iconName": "analytics"
6267
6283
  },
6268
6284
  {
6269
6285
  "displayName": "Queues",
@@ -6271,7 +6287,8 @@
6271
6287
  "sequenceNumber": 2,
6272
6288
  "actionUserKey": "mqMessageQueue-list-action",
6273
6289
  "moduleUserKey": "solid-core",
6274
- "parentMenuItemUserKey": "queues-menu-item"
6290
+ "parentMenuItemUserKey": "queues-menu-item",
6291
+ "iconName": "dns"
6275
6292
  },
6276
6293
  {
6277
6294
  "displayName": "Messages",
@@ -6279,7 +6296,8 @@
6279
6296
  "sequenceNumber": 3,
6280
6297
  "actionUserKey": "mqMessage-list-action",
6281
6298
  "moduleUserKey": "solid-core",
6282
- "parentMenuItemUserKey": "queues-menu-item"
6299
+ "parentMenuItemUserKey": "queues-menu-item",
6300
+ "iconName": "message"
6283
6301
  },
6284
6302
  {
6285
6303
  "displayName": "Notification",
@@ -6288,7 +6306,7 @@
6288
6306
  "actionUserKey": "",
6289
6307
  "moduleUserKey": "solid-core",
6290
6308
  "parentMenuItemUserKey": "",
6291
- "iconName": "notification_settings"
6309
+ "iconName": "notification_add"
6292
6310
  },
6293
6311
  {
6294
6312
  "displayName": "Email",
@@ -6296,7 +6314,8 @@
6296
6314
  "sequenceNumber": 1,
6297
6315
  "actionUserKey": "emailTemplate-list-action",
6298
6316
  "moduleUserKey": "solid-core",
6299
- "parentMenuItemUserKey": "notification-menu-item"
6317
+ "parentMenuItemUserKey": "notification-menu-item",
6318
+ "iconName": "email"
6300
6319
  },
6301
6320
  {
6302
6321
  "displayName": "SMS",
@@ -6304,7 +6323,8 @@
6304
6323
  "sequenceNumber": 2,
6305
6324
  "actionUserKey": "smsTemplate-list-action",
6306
6325
  "moduleUserKey": "solid-core",
6307
- "parentMenuItemUserKey": "notification-menu-item"
6326
+ "parentMenuItemUserKey": "notification-menu-item",
6327
+ "iconName": "sms"
6308
6328
  },
6309
6329
  {
6310
6330
  "displayName": "Other",
@@ -6313,7 +6333,7 @@
6313
6333
  "actionUserKey": "",
6314
6334
  "moduleUserKey": "solid-core",
6315
6335
  "parentMenuItemUserKey": "",
6316
- "iconName": "other_admission"
6336
+ "iconName": "more_horiz"
6317
6337
  },
6318
6338
  {
6319
6339
  "displayName": "List of Values",
@@ -6321,7 +6341,8 @@
6321
6341
  "sequenceNumber": 1,
6322
6342
  "actionUserKey": "listOfValues-list-action",
6323
6343
  "moduleUserKey": "solid-core",
6324
- "parentMenuItemUserKey": "other-menu-item"
6344
+ "parentMenuItemUserKey": "other-menu-item",
6345
+ "iconName": "list"
6325
6346
  },
6326
6347
  {
6327
6348
  "displayName": "Scheduled Jobs",
@@ -6329,7 +6350,8 @@
6329
6350
  "sequenceNumber": 2,
6330
6351
  "actionUserKey": "scheduledJob-list-action",
6331
6352
  "moduleUserKey": "solid-core",
6332
- "parentMenuItemUserKey": "other-menu-item"
6353
+ "parentMenuItemUserKey": "other-menu-item",
6354
+ "iconName": "event_repeat"
6333
6355
  },
6334
6356
  {
6335
6357
  "displayName": "Saved Filters",
@@ -6337,7 +6359,8 @@
6337
6359
  "sequenceNumber": 4,
6338
6360
  "actionUserKey": "savedFilters-list-action",
6339
6361
  "moduleUserKey": "solid-core",
6340
- "parentMenuItemUserKey": "other-menu-item"
6362
+ "parentMenuItemUserKey": "other-menu-item",
6363
+ "iconName": "filter_list_alt"
6341
6364
  },
6342
6365
  {
6343
6366
  "displayName": "Chatter Message",
@@ -6345,7 +6368,8 @@
6345
6368
  "sequenceNumber": 5,
6346
6369
  "actionUserKey": "chatterMessage-list-action",
6347
6370
  "moduleUserKey": "solid-core",
6348
- "parentMenuItemUserKey": "other-menu-item"
6371
+ "parentMenuItemUserKey": "other-menu-item",
6372
+ "iconName": "forum"
6349
6373
  },
6350
6374
  {
6351
6375
  "displayName": "Locale",
@@ -6353,7 +6377,8 @@
6353
6377
  "sequenceNumber": 7,
6354
6378
  "actionUserKey": "locale-list-action",
6355
6379
  "moduleUserKey": "solid-core",
6356
- "parentMenuItemUserKey": "other-menu-item"
6380
+ "parentMenuItemUserKey": "other-menu-item",
6381
+ "iconName": "language"
6357
6382
  },
6358
6383
  {
6359
6384
  "displayName": "Import Transactions",
@@ -6361,7 +6386,8 @@
6361
6386
  "sequenceNumber": 8,
6362
6387
  "actionUserKey": "importTransaction-list-action",
6363
6388
  "moduleUserKey": "solid-core",
6364
- "parentMenuItemUserKey": "other-menu-item"
6389
+ "parentMenuItemUserKey": "other-menu-item",
6390
+ "iconName": "upload_file"
6365
6391
  },
6366
6392
  {
6367
6393
  "displayName": "Settings",
@@ -6378,7 +6404,8 @@
6378
6404
  "sequenceNumber": 1,
6379
6405
  "actionUserKey": "modelSequence-list-action",
6380
6406
  "moduleUserKey": "solid-core",
6381
- "parentMenuItemUserKey": "other-menu-item"
6407
+ "parentMenuItemUserKey": "other-menu-item",
6408
+ "iconName": "format_list_numbered"
6382
6409
  },
6383
6410
  {
6384
6411
  "displayName": "Dashboard User Layout",
@@ -6387,7 +6414,7 @@
6387
6414
  "actionUserKey": "dashboardUserLayout-list-action",
6388
6415
  "moduleUserKey": "solid-core",
6389
6416
  "parentMenuItemUserKey": "",
6390
- "iconName": ""
6417
+ "iconName": "dashboard_customize"
6391
6418
  },
6392
6419
  {
6393
6420
  "displayName": "Agent",
@@ -6404,7 +6431,8 @@
6404
6431
  "sequenceNumber": 1,
6405
6432
  "actionUserKey": "agentSession-list-action",
6406
6433
  "moduleUserKey": "solid-core",
6407
- "parentMenuItemUserKey": "agent-menu-item"
6434
+ "parentMenuItemUserKey": "agent-menu-item",
6435
+ "iconName": "chat"
6408
6436
  },
6409
6437
  {
6410
6438
  "displayName": "MCP Audit Log",
@@ -6412,7 +6440,8 @@
6412
6440
  "sequenceNumber": 3,
6413
6441
  "actionUserKey": "mcpAuditLog-list-action",
6414
6442
  "moduleUserKey": "solid-core",
6415
- "parentMenuItemUserKey": "agent-menu-item"
6443
+ "parentMenuItemUserKey": "agent-menu-item",
6444
+ "iconName": "fact_check"
6416
6445
  }
6417
6446
  ],
6418
6447
  "views": [
@@ -1042,13 +1042,15 @@ export class AuthenticationService {
1042
1042
  }
1043
1043
 
1044
1044
  const type = this.resolveLoginType(signInDto);
1045
- const user = await this.findUserForLogin(type, signInDto.identifier);
1046
- const dummyOtp = this.getDummyOtpForUser(user);
1047
- if (!dummyOtp) {
1048
- await this.assignLoginOtp(user, type);
1049
- await this.notifyUserOnOtpInititateLogin(user, type);
1045
+ const user = await this.findUserForLoginOrNull(type, signInDto.identifier);
1046
+ if (user) {
1047
+ const dummyOtp = this.getDummyOtpForUser(user);
1048
+ if (!dummyOtp) {
1049
+ await this.assignLoginOtp(user, type);
1050
+ await this.notifyUserOnOtpInititateLogin(user, type);
1051
+ }
1050
1052
  }
1051
- return this.buildLoginOtpResponse(user, type);
1053
+ return this.buildLoginOtpResponse(type, signInDto.identifier, user);
1052
1054
  }
1053
1055
 
1054
1056
  private resolveLoginType(
@@ -1100,6 +1102,25 @@ export class AuthenticationService {
1100
1102
  return user;
1101
1103
  }
1102
1104
 
1105
+ private async findUserForLoginOrNull(
1106
+ type: PasswordlessLoginValidateWhatSources,
1107
+ identifier: string,
1108
+ options: { withRoles?: boolean } = {},
1109
+ ): Promise<User | null> {
1110
+ try {
1111
+ return await this.findUserForLogin(type, identifier, options);
1112
+ } catch (error) {
1113
+ if (
1114
+ error instanceof UnauthorizedException &&
1115
+ (error.message === ERROR_MESSAGES.USER_NOT_FOUND ||
1116
+ error.message === ERROR_MESSAGES.USER_INACTIVE)
1117
+ ) {
1118
+ return null;
1119
+ }
1120
+ throw error;
1121
+ }
1122
+ }
1123
+
1103
1124
  private async assignLoginOtp(
1104
1125
  user: User,
1105
1126
  type: PasswordlessLoginValidateWhatSources,
@@ -1123,19 +1144,29 @@ export class AuthenticationService {
1123
1144
  }
1124
1145
 
1125
1146
  private buildLoginOtpResponse(
1126
- user: User,
1127
1147
  type: PasswordlessLoginValidateWhatSources,
1148
+ identifier: string,
1149
+ user?: User | null,
1128
1150
  ) {
1129
- const maskedIdentifier =
1130
- type === PasswordlessLoginValidateWhatSources.EMAIL
1131
- ? { email: this.maskEmail(user.email) }
1132
- : { mobile: this.maskMobile(user.mobile) };
1151
+ const maskedIdentifier = this.buildMaskedLoginIdentifier(
1152
+ type,
1153
+ user?.email ?? user?.mobile ?? identifier,
1154
+ );
1133
1155
  return {
1134
1156
  message: SUCCESS_MESSAGES.OTP_SENT_SUCCESS_LOGIN,
1135
1157
  user: maskedIdentifier,
1136
1158
  };
1137
1159
  }
1138
1160
 
1161
+ private buildMaskedLoginIdentifier(
1162
+ type: PasswordlessLoginValidateWhatSources,
1163
+ identifier: string,
1164
+ ) {
1165
+ return type === PasswordlessLoginValidateWhatSources.EMAIL
1166
+ ? { email: this.maskEmail(identifier) }
1167
+ : { mobile: this.maskMobile(identifier) };
1168
+ }
1169
+
1139
1170
  private async notifyUserOnOtpInititateLogin(
1140
1171
  user: User,
1141
1172
  loginType: PasswordlessLoginValidateWhatSources,
@@ -1273,9 +1304,12 @@ export class AuthenticationService {
1273
1304
  throw new BadRequestException(ERROR_MESSAGES.INVALID_VERIFICATION_TYPE);
1274
1305
  }
1275
1306
 
1276
- const user = await this.findUserForLogin(type, identifier, {
1307
+ const user = await this.findUserForLoginOrNull(type, identifier, {
1277
1308
  withRoles: true,
1278
1309
  });
1310
+ if (!user) {
1311
+ throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
1312
+ }
1279
1313
  this.checkAccountBlocked(user);
1280
1314
  const dummyOtp = this.getDummyOtpForUser(user);
1281
1315
 
@@ -45,12 +45,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
45
45
  }
46
46
  }
47
47
 
48
- // Use the originating transaction's EntityManager so the uniqueness check runs on the
49
- // active connection. Falls back to the injected manager only when no event context is
50
- // available (e.g. direct invocation outside a TypeORM lifecycle event).
51
- const manager = eventContext?.manager ?? this.entityManager;
52
-
53
- const uniqueCode = await this.generateUniqueExternalId(manager, resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
48
+ const uniqueCode = await this.generateUniqueExternalId(resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
54
49
  const finalExternalId = resolvedPrefix ? `${resolvedPrefix}-${uniqueCode}` : uniqueCode;
55
50
 
56
51
  triggerEntity[computedFieldMetadata.fieldName] = finalExternalId;
@@ -65,8 +60,8 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
65
60
  return result;
66
61
  }
67
62
 
68
- private async isExternalIdUnique(manager: EntityManager, externalId: string, fieldName: string, entityName: string): Promise<boolean> {
69
- const count = await manager.count(entityName as any,
63
+ private async isExternalIdUnique(externalId: string, fieldName: string, entityName: string): Promise<boolean> {
64
+ const count = await this.entityManager.count(entityName as any,
70
65
  {
71
66
  where: { [fieldName]: externalId },
72
67
  }
@@ -74,7 +69,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
74
69
  return count === 0;
75
70
  }
76
71
 
77
- private async generateUniqueExternalId(manager: EntityManager, resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {
72
+ private async generateUniqueExternalId(resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {
78
73
  const maxAttempts = 10;
79
74
 
80
75
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -83,7 +78,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
83
78
 
84
79
  const fullId = resolvedPrefix ? `${resolvedPrefix}-${newId}` : newId;
85
80
 
86
- const isUnique = await this.isExternalIdUnique(manager, fullId, fieldName, entityName);
81
+ const isUnique = await this.isExternalIdUnique(fullId, fieldName, entityName);
87
82
 
88
83
  if (isUnique) {
89
84
  return newId;