@solidxai/core 0.1.6-beta.21 → 0.1.6-beta.23

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 (42) hide show
  1. package/.claude/settings.local.json +15 -0
  2. package/dist/helpers/solid-registry.d.ts +3 -0
  3. package/dist/helpers/solid-registry.d.ts.map +1 -1
  4. package/dist/helpers/solid-registry.js +7 -0
  5. package/dist/helpers/solid-registry.js.map +1 -1
  6. package/dist/repository/model-metadata.repository.d.ts +6 -1
  7. package/dist/repository/model-metadata.repository.d.ts.map +1 -1
  8. package/dist/repository/model-metadata.repository.js +41 -2
  9. package/dist/repository/model-metadata.repository.js.map +1 -1
  10. package/dist/services/model-metadata.service.d.ts +1 -4
  11. package/dist/services/model-metadata.service.d.ts.map +1 -1
  12. package/dist/services/model-metadata.service.js +2 -31
  13. package/dist/services/model-metadata.service.js.map +1 -1
  14. package/dist/services/queues/publisher-factory.service.js +0 -1
  15. package/dist/services/queues/publisher-factory.service.js.map +1 -1
  16. package/dist/services/solid-introspect.service.d.ts +6 -1
  17. package/dist/services/solid-introspect.service.d.ts.map +1 -1
  18. package/dist/services/solid-introspect.service.js +27 -2
  19. package/dist/services/solid-introspect.service.js.map +1 -1
  20. package/dist/subscribers/audit.subscriber.d.ts +3 -5
  21. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  22. package/dist/subscribers/audit.subscriber.js +9 -38
  23. package/dist/subscribers/audit.subscriber.js.map +1 -1
  24. package/logs_load_testing +49 -0
  25. package/package.json +1 -1
  26. package/src/helpers/solid-registry.ts +9 -0
  27. package/src/repository/model-metadata.repository.ts +45 -2
  28. package/src/services/1.js +6 -0
  29. package/src/services/model-metadata.service.ts +0 -42
  30. package/src/services/queues/publisher-factory.service.ts +1 -1
  31. package/src/services/solid-introspect.service.ts +28 -0
  32. package/src/subscribers/audit.subscriber.ts +9 -52
  33. package/dist-tests/api/authenticate.spec.js +0 -119
  34. package/dist-tests/api/authenticate.spec.js.map +0 -1
  35. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +0 -97
  36. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +0 -1
  37. package/dist-tests/api/ping.spec.js +0 -21
  38. package/dist-tests/api/ping.spec.js.map +0 -1
  39. package/dist-tests/helpers/auth.js +0 -41
  40. package/dist-tests/helpers/auth.js.map +0 -1
  41. package/dist-tests/helpers/env.js +0 -11
  42. package/dist-tests/helpers/env.js.map +0 -1
@@ -14,6 +14,8 @@ exports.SolidIntrospectService = exports.coreSubscriberClasses = void 0;
14
14
  const strings_1 = require("@angular-devkit/core/src/utils/strings");
15
15
  const common_1 = require("@nestjs/common");
16
16
  const core_1 = require("@nestjs/core");
17
+ const model_metadata_helper_service_1 = require("../helpers/model-metadata-helper.service");
18
+ const model_metadata_repository_1 = require("../repository/model-metadata.repository");
17
19
  const typeorm_1 = require("@nestjs/typeorm");
18
20
  const computed_field_provider_decorator_1 = require("../decorators/computed-field-provider.decorator");
19
21
  const dashboard_question_data_provider_decorator_1 = require("../decorators/dashboard-question-data-provider.decorator");
@@ -40,13 +42,15 @@ exports.coreSubscriberClasses = [
40
42
  soft_delete_aware_event_subscriber_1.SoftDeleteAwareEventSubscriber
41
43
  ];
42
44
  let SolidIntrospectService = SolidIntrospectService_1 = class SolidIntrospectService {
43
- constructor(discoveryService, reflector, metadataScanner, solidRegistry, moduleRef, settingService) {
45
+ constructor(discoveryService, reflector, metadataScanner, solidRegistry, moduleRef, settingService, modelMetadataRepo, modelMetadataHelperService) {
44
46
  this.discoveryService = discoveryService;
45
47
  this.reflector = reflector;
46
48
  this.metadataScanner = metadataScanner;
47
49
  this.solidRegistry = solidRegistry;
48
50
  this.moduleRef = moduleRef;
49
51
  this.settingService = settingService;
52
+ this.modelMetadataRepo = modelMetadataRepo;
53
+ this.modelMetadataHelperService = modelMetadataHelperService;
50
54
  this.logger = new common_1.Logger(SolidIntrospectService_1.name);
51
55
  }
52
56
  async onApplicationBootstrap() {
@@ -114,8 +118,27 @@ let SolidIntrospectService = SolidIntrospectService_1 = class SolidIntrospectSer
114
118
  this.solidRegistry.registerSecurityRuleConfigProvider(securityRuleConfigProvider);
115
119
  });
116
120
  await this.bootstrapCoreTypeOrmSubscribers(solidDatabaseModules);
121
+ await this.cacheAuditableModels();
117
122
  await this.settingService.updateSettingsCache();
118
123
  }
124
+ async cacheAuditableModels() {
125
+ const models = await this.modelMetadataRepo.find({
126
+ where: { enableAuditTracking: true },
127
+ relations: { fields: true, module: true },
128
+ });
129
+ const auditableSet = new Set();
130
+ for (const model of models) {
131
+ const allFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName);
132
+ const hasAuditableField = allFields.some(field => field.enableAuditTracking &&
133
+ !['mediaSingle', 'mediaMultiple', 'richText', 'json'].includes(field.type) &&
134
+ !(field.type === 'relation' && field.relationType === 'one-to-many'));
135
+ if (hasAuditableField) {
136
+ auditableSet.add(model.singularName.toLowerCase());
137
+ }
138
+ }
139
+ this.solidRegistry.registerAuditableModels(auditableSet);
140
+ this.logger.debug(`Cached ${auditableSet.size} auditable model(s): ${[...auditableSet].join(', ')}`);
141
+ }
119
142
  async bootstrapCoreTypeOrmSubscribers(dbModules) {
120
143
  for (const wrapper of dbModules) {
121
144
  const instance = wrapper.instance;
@@ -277,6 +300,8 @@ exports.SolidIntrospectService = SolidIntrospectService = SolidIntrospectService
277
300
  core_1.MetadataScanner,
278
301
  solid_registry_1.SolidRegistry,
279
302
  core_1.ModuleRef,
280
- setting_service_1.SettingService])
303
+ setting_service_1.SettingService,
304
+ model_metadata_repository_1.ModelMetadataRepository,
305
+ model_metadata_helper_service_1.ModelMetadataHelperService])
281
306
  ], SolidIntrospectService);
282
307
  //# sourceMappingURL=solid-introspect.service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"solid-introspect.service.js","sourceRoot":"","sources":["../../src/services/solid-introspect.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { classify } from '@angular-devkit/core/src/utils/strings';\nimport { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';\nimport { DiscoveryService, MetadataScanner, ModuleRef, Reflector } from '@nestjs/core';\nimport { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';\nimport { getDataSourceToken } from '@nestjs/typeorm';\nimport { IS_COMPUTED_FIELD_PROVIDER } from 'src/decorators/computed-field-provider.decorator';\nimport { IS_DASHBOARD_QUESTION_DATA_PROVIDER } from 'src/decorators/dashboard-question-data-provider.decorator';\nimport { IS_DASHBOARD_VARIABLE_SELECTION_PROVIDER } from 'src/decorators/dashboard-selection-provider.decorator';\nimport { IS_ERROR_CODE_PROVIDER } from 'src/decorators/error-codes-provider.decorator';\nimport { IS_MAIL_PROVIDER } from 'src/decorators/mail-provider.decorator';\nimport { IS_SCHEDULED_JOB_PROVIDER } from 'src/decorators/scheduled-job-provider.decorator';\nimport { IS_SECURITY_RULE_CONFIG_PROVIDER } from 'src/decorators/security-rule-config-provider.decorator';\nimport { IS_SELECTION_PROVIDER } from 'src/decorators/selection-provider.decorator';\nimport { IS_SOLID_DATABASE_MODULE } from 'src/decorators/solid-database-module.decorator';\nimport { IS_WA_PROVIDER } from 'src/decorators/whatsapp-provider.decorator';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { AuditSubscriber } from 'src/subscribers/audit.subscriber';\nimport { ComputedEntityFieldSubscriber } from 'src/subscribers/computed-entity-field.subscriber';\nimport { CreatedByUpdatedBySubscriber } from 'src/subscribers/created-by-updated-by.subscriber';\nimport { SoftDeleteAwareEventSubscriber } from 'src/subscribers/soft-delete-aware-event.subscriber';\nimport { DataSource } from 'typeorm';\nimport { CRUDService } from './crud.service';\nimport { IS_SETTINGS_PROVIDER } from 'src/decorators/settings-provider.decorator';\nimport { IS_SMS_PROVIDER } from 'src/decorators/sms-provider.decorator';\nimport { SettingService } from 'src/services/setting.service';\n\nexport const coreSubscriberClasses = [\n AuditSubscriber,\n ComputedEntityFieldSubscriber,\n CreatedByUpdatedBySubscriber,\n SoftDeleteAwareEventSubscriber\n];\n\n@Injectable()\nexport class SolidIntrospectService implements OnApplicationBootstrap {\n constructor(\n private readonly discoveryService: DiscoveryService,\n private readonly reflector: Reflector,\n private readonly metadataScanner: MetadataScanner,\n private readonly solidRegistry: SolidRegistry,\n private readonly moduleRef: ModuleRef,\n private readonly settingService: SettingService,\n ) { }\n\n private readonly logger = new Logger(SolidIntrospectService.name);\n\n async onApplicationBootstrap() {\n this.logger.debug('Introspecting the application for Solid metadata');\n\n // Register all seeders\n const seeders = this.discoveryService.getProviders().filter((provider) => this.isSeeder(provider));\n seeders.forEach((seeder) => {\n this.solidRegistry.registerSeeder(seeder);\n });\n\n // Register all IErrorCodeProvider implementations\n const errorCodeProviders = this.discoveryService.getProviders().filter((provider) => this.isErrorCodeProvider(provider));\n errorCodeProviders.forEach((errorCodeProvider) => {\n this.solidRegistry.registerErrorCodeProvider(errorCodeProvider);\n });\n\n // Register all ISelectionProvider implementations\n const selectionProviders = this.discoveryService.getProviders().filter((provider) => this.isSelectionProvider(provider));\n selectionProviders.forEach((selectionProvider) => {\n this.solidRegistry.registerSelectionProvider(selectionProvider);\n });\n\n // Register all ISettingsProvider implementations\n const settingsProviders = this.discoveryService.getProviders().filter((provider) => this.isSettingsProvider(provider));\n settingsProviders.forEach((settingsProvider) => {\n this.solidRegistry.registerSettingsProvider(settingsProvider);\n });\n\n // Register all IDashboardSelectionProvider implementations\n const dashboardVariableSelectionProviders = this.discoveryService.getProviders().filter((provider) => this.isDashboardVariableSelectionProvider(provider));\n dashboardVariableSelectionProviders.forEach((dashboardSelectionProvider) => {\n this.solidRegistry.registerDashboardVariableSelectionProvider(dashboardSelectionProvider);\n });\n\n // Register all IDashboardSelectionProvider implementations\n const dashboardQuestionDataProviders = this.discoveryService.getProviders().filter((provider) => this.isDashboardQuestionDataProvider(provider));\n dashboardQuestionDataProviders.forEach((provider) => {\n this.solidRegistry.registerDashboardQuestionDataProvider(provider);\n });\n\n // Register all IComputedProvider implementations\n const computedFieldProviders = this.discoveryService.getProviders().filter((provider) => this.isComputedFieldProvider(provider));\n computedFieldProviders.forEach((computedFieldProvider) => {\n this.solidRegistry.registerComputedFieldProvider(computedFieldProvider);\n });\n\n // Register all ISolidDatabaseModules implementations\n const solidDatabaseModules = this.discoveryService.getProviders().filter((provider) => this.isSolidDatabaseModule(provider));\n solidDatabaseModules.forEach((solidDatabaseModule) => {\n this.solidRegistry.registerSolidDatabaseModule(solidDatabaseModule);\n });\n\n // keep track of all the controllers & respective methods. \n const allControllers = this.discoveryService.getControllers().map((controller) => {\n const { instance } = controller;\n return {\n name: controller.name,\n methods: this.metadataScanner.getAllMethodNames(Object.getPrototypeOf(instance))\n };\n });\n\n this.solidRegistry.registerControllers(new Set(allControllers));\n\n // Register all modules\n const allModules = this.discoveryService.getProviders().filter((provider) => this.isModule(provider));\n this.solidRegistry.registerModules(allModules);\n\n // Register all IScheduledJob implementations\n const scheduledJobProviders = this.discoveryService.getProviders().filter((provider) => this.isScheduledJobProvider(provider));\n scheduledJobProviders.forEach((scheduledJobProvider) => {\n this.solidRegistry.registerScheduledJobProvider(scheduledJobProvider);\n });\n\n // Register all IMail implementations\n const mailProviders = this.discoveryService.getProviders().filter((provider) => this.isMailProvider(provider));\n mailProviders.forEach((mailProvider) => {\n this.solidRegistry.registerMailProvider(mailProvider);\n });\n\n // Register all IWhatsappTransport implementations\n const whatsappProviders = this.discoveryService.getProviders().filter((provider) => this.isWhatsappProvider(provider));\n whatsappProviders.forEach((whatsappProvider) => {\n this.solidRegistry.registerWhatsappProvider(whatsappProvider);\n });\n\n // Register all IWhatsappTransport implementations\n const smsProviders = this.discoveryService.getProviders().filter((provider) => this.isSmsProvider(provider));\n smsProviders.forEach((smsProvider) => {\n this.solidRegistry.registerSmsProvider(smsProvider);\n });\n\n // Register all ISecurityRuleConfigProvider implementations\n const securityRuleConfigProviders = this.discoveryService.getProviders().filter((provider) => this.isSecurityRuleConfigProvider(provider));\n securityRuleConfigProviders.forEach((securityRuleConfigProvider) => {\n this.solidRegistry.registerSecurityRuleConfigProvider(securityRuleConfigProvider);\n });\n\n // Register the core subscribers against all the configured database modules / datasources\n await this.bootstrapCoreTypeOrmSubscribers(solidDatabaseModules);\n await this.settingService.updateSettingsCache();\n }\n\n async bootstrapCoreTypeOrmSubscribers(dbModules: Array<InstanceWrapper<any>>): Promise<void> {\n // Register core subscribers for each Solid database module\n for (const wrapper of dbModules) {\n // Get the Database Module instance\n const instance = (wrapper as InstanceWrapper).instance as any;\n if (!instance || typeof instance.name !== 'function') {\n this.logger.warn('Skipping a solid DB module wrapper with no instance or name() method');\n continue;\n }\n\n // Get the DataSource for this module\n const dsName: string | undefined = instance.name();\n // getDataSourceToken() without name = default; pass dsName if non-default\n const token = dsName ? getDataSourceToken(dsName) : getDataSourceToken();\n let ds: DataSource | undefined;\n try {\n ds = this.moduleRef.get<DataSource>(token, { strict: false });\n } catch (err) {\n this.logger.warn(`DataSource token for \"${dsName ?? 'default'}\" not found: ${err?.message ?? err}`);\n }\n if (!ds) {\n this.logger.warn(`No DataSource found for module \"${dsName}\". Skipping subscriber registration.`);\n continue;\n }\n\n // Ensure DataSource is initialized (optional)\n if (!ds.isInitialized) {\n try {\n await ds.initialize(); // only if you need to initialize here; in many apps datasources are created earlier\n } catch (err) {\n this.logger.error(`Failed to initialize DataSource \"${dsName}\": ${err}`);\n continue;\n }\n }\n\n // Register each subscriber class for this DataSource\n // const auditSubscriberInstance = new AuditSubscriber(this.chatterMessageService, this.modelMetadataRepo, this.modelMetadataHelperService);\n // auditSubscriberInstance.bindToDataSource(ds);\n\n // const computedEntityFieldSubscriberInstance = new ComputedEntityFieldSubscriber(this.solidRegistry, this.publisherFactory);\n // computedEntityFieldSubscriberInstance.bindToDataSource(ds);\n\n // const createdByUpdatedBySubscriberInstance = new CreatedByUpdatedBySubscriber(this.requestContextService);\n // createdByUpdatedBySubscriberInstance.bindToDataSource(ds);\n\n // const softDeleteAwareEventSubscriberInstance = new SoftDeleteAwareEventSubscriber();\n // softDeleteAwareEventSubscriberInstance.bindToDataSource(ds);\n for (const SubClass of coreSubscriberClasses) {\n const alreadyRegistered = ds.subscribers.some(\n (s) => (s as any).constructor?.name === SubClass.name,\n );\n if (alreadyRegistered) {\n this.logger.debug(`Subscriber ${SubClass.name} already registered on datasource ${dsName ?? 'default'}`);\n continue;\n }\n\n // Resolve subscriber from NestJS moduleRef to ensure dependencies are injected\n const subscriberInstance = await this.moduleRef.resolve(SubClass, undefined, { strict: false });\n subscriberInstance.bindToDataSource(ds);\n\n // instantiate subscriber bound to this DataSource\n // NOTE: constructor signature must be (dataSource: DataSource, requestContextService: RequestContextService, ...)\n // const subscriberInstance = new (SubClass as any)(ds, this.requestContextService);\n\n // ds.subscribers.push(subscriberInstance);\n // this.logger.log(`Registered subscriber ${SubClass.name} on datasource ${dsName ?? 'default'}`);\n }\n }\n }\n\n isDashboardQuestionDataProvider(providerWrapper: InstanceWrapper<any>) {\n const { instance } = providerWrapper;\n if (!instance) return false;\n const provider = this.reflector.get<boolean>(\n IS_DASHBOARD_QUESTION_DATA_PROVIDER,\n instance.constructor,\n );\n return !!provider;\n }\n\n // This method identifies a provider as a seeder if it has a seed method i.e duck typing\n private isSeeder(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const seedMethod = this.metadataScanner.getAllMethodNames(Object.getPrototypeOf(instance)).find((methodName) => methodName === 'seed');\n if (!seedMethod) return false;\n return true;\n }\n\n private isErrorCodeProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isErrorCodeProvider = this.reflector.get<boolean>(\n IS_ERROR_CODE_PROVIDER,\n instance.constructor,\n );\n\n return !!isErrorCodeProvider;\n }\n\n private isSelectionProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSelectionProvider = this.reflector.get<boolean>(\n IS_SELECTION_PROVIDER,\n instance.constructor,\n );\n\n return !!isSelectionProvider;\n }\n\n private isSettingsProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSettingsProvider = this.reflector.get<boolean>(\n IS_SETTINGS_PROVIDER,\n instance.constructor,\n );\n\n return !!isSettingsProvider;\n }\n\n private isDashboardVariableSelectionProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n const isDashboardSelectionProvider = this.reflector.get<boolean>(\n IS_DASHBOARD_VARIABLE_SELECTION_PROVIDER,\n instance.constructor,\n );\n return !!isDashboardSelectionProvider;\n }\n\n private isComputedFieldProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isComputedFieldProvider = this.reflector.get<boolean>(\n IS_COMPUTED_FIELD_PROVIDER,\n instance.constructor,\n );\n\n return !!isComputedFieldProvider;\n }\n\n private isScheduledJobProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isScheduledJobProvider = this.reflector.get<boolean>(\n IS_SCHEDULED_JOB_PROVIDER,\n instance.constructor,\n );\n\n return !!isScheduledJobProvider;\n }\n\n private isSolidDatabaseModule(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSolidDatabaseModule = this.reflector.get<boolean>(\n IS_SOLID_DATABASE_MODULE,\n instance.constructor,\n );\n\n return !!isSolidDatabaseModule;\n }\n\n private isMailProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isMailProvider = this.reflector.get<boolean>(\n IS_MAIL_PROVIDER,\n instance.constructor,\n );\n\n return !!isMailProvider;\n }\n\n private isWhatsappProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isWhatsappProvider = this.reflector.get<boolean>(\n IS_WA_PROVIDER,\n instance.constructor,\n );\n\n return !!isWhatsappProvider;\n }\n\n private isSmsProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSmsProvider = this.reflector.get<boolean>(\n IS_SMS_PROVIDER,\n instance.constructor,\n );\n\n return !!isSmsProvider;\n }\n\n private isSecurityRuleConfigProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSecurityRuleConfigProvider = this.reflector.get<boolean>(\n IS_SECURITY_RULE_CONFIG_PROVIDER,\n instance.constructor,\n );\n\n return !!isSecurityRuleConfigProvider;\n }\n\n private isModule(provider: InstanceWrapper): boolean {\n const metatype = provider.metatype;\n // Check if it's a Static Module (Class-Based)\n if (metatype && typeof metatype === 'function' && Reflect.getMetadata('imports', metatype)) {\n return true;\n }\n\n // Ensure provider.instance is an object before checking for 'module'\n if (provider.instance && typeof provider.instance === 'object') {\n // Check if it's a Dynamic Module (Object-Based)\n if ('module' in provider.instance && typeof provider.instance.module === 'function') {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Given a model singular name this will return the crud service instance.\n * @param modelSingularName \n * @returns \n */\n getCRUDService(modelSingularName: string): CRUDService<any> {\n const provider = this.getProvider(`${classify(modelSingularName)}Service`);\n return provider?.instance as CRUDService<any>;\n }\n\n getProvider(providerName: string) {\n return this.discoveryService.getProviders().find((provider) => provider.name === providerName);\n }\n}\n"]}
1
+ {"version":3,"file":"solid-introspect.service.js","sourceRoot":"","sources":["../../src/services/solid-introspect.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { classify } from '@angular-devkit/core/src/utils/strings';\nimport { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';\nimport { DiscoveryService, MetadataScanner, ModuleRef, Reflector } from '@nestjs/core';\nimport { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\nimport { ModelMetadataRepository } from 'src/repository/model-metadata.repository';\nimport { InstanceWrapper } from '@nestjs/core/injector/instance-wrapper';\nimport { getDataSourceToken } from '@nestjs/typeorm';\nimport { IS_COMPUTED_FIELD_PROVIDER } from 'src/decorators/computed-field-provider.decorator';\nimport { IS_DASHBOARD_QUESTION_DATA_PROVIDER } from 'src/decorators/dashboard-question-data-provider.decorator';\nimport { IS_DASHBOARD_VARIABLE_SELECTION_PROVIDER } from 'src/decorators/dashboard-selection-provider.decorator';\nimport { IS_ERROR_CODE_PROVIDER } from 'src/decorators/error-codes-provider.decorator';\nimport { IS_MAIL_PROVIDER } from 'src/decorators/mail-provider.decorator';\nimport { IS_SCHEDULED_JOB_PROVIDER } from 'src/decorators/scheduled-job-provider.decorator';\nimport { IS_SECURITY_RULE_CONFIG_PROVIDER } from 'src/decorators/security-rule-config-provider.decorator';\nimport { IS_SELECTION_PROVIDER } from 'src/decorators/selection-provider.decorator';\nimport { IS_SOLID_DATABASE_MODULE } from 'src/decorators/solid-database-module.decorator';\nimport { IS_WA_PROVIDER } from 'src/decorators/whatsapp-provider.decorator';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { AuditSubscriber } from 'src/subscribers/audit.subscriber';\nimport { ComputedEntityFieldSubscriber } from 'src/subscribers/computed-entity-field.subscriber';\nimport { CreatedByUpdatedBySubscriber } from 'src/subscribers/created-by-updated-by.subscriber';\nimport { SoftDeleteAwareEventSubscriber } from 'src/subscribers/soft-delete-aware-event.subscriber';\nimport { DataSource } from 'typeorm';\nimport { CRUDService } from './crud.service';\nimport { IS_SETTINGS_PROVIDER } from 'src/decorators/settings-provider.decorator';\nimport { IS_SMS_PROVIDER } from 'src/decorators/sms-provider.decorator';\nimport { SettingService } from 'src/services/setting.service';\n\nexport const coreSubscriberClasses = [\n AuditSubscriber,\n ComputedEntityFieldSubscriber,\n CreatedByUpdatedBySubscriber,\n SoftDeleteAwareEventSubscriber\n];\n\n@Injectable()\nexport class SolidIntrospectService implements OnApplicationBootstrap {\n constructor(\n private readonly discoveryService: DiscoveryService,\n private readonly reflector: Reflector,\n private readonly metadataScanner: MetadataScanner,\n private readonly solidRegistry: SolidRegistry,\n private readonly moduleRef: ModuleRef,\n private readonly settingService: SettingService,\n private readonly modelMetadataRepo: ModelMetadataRepository,\n private readonly modelMetadataHelperService: ModelMetadataHelperService,\n ) { }\n\n private readonly logger = new Logger(SolidIntrospectService.name);\n\n async onApplicationBootstrap() {\n this.logger.debug('Introspecting the application for Solid metadata');\n\n // Register all seeders\n const seeders = this.discoveryService.getProviders().filter((provider) => this.isSeeder(provider));\n seeders.forEach((seeder) => {\n this.solidRegistry.registerSeeder(seeder);\n });\n\n // Register all IErrorCodeProvider implementations\n const errorCodeProviders = this.discoveryService.getProviders().filter((provider) => this.isErrorCodeProvider(provider));\n errorCodeProviders.forEach((errorCodeProvider) => {\n this.solidRegistry.registerErrorCodeProvider(errorCodeProvider);\n });\n\n // Register all ISelectionProvider implementations\n const selectionProviders = this.discoveryService.getProviders().filter((provider) => this.isSelectionProvider(provider));\n selectionProviders.forEach((selectionProvider) => {\n this.solidRegistry.registerSelectionProvider(selectionProvider);\n });\n\n // Register all ISettingsProvider implementations\n const settingsProviders = this.discoveryService.getProviders().filter((provider) => this.isSettingsProvider(provider));\n settingsProviders.forEach((settingsProvider) => {\n this.solidRegistry.registerSettingsProvider(settingsProvider);\n });\n\n // Register all IDashboardSelectionProvider implementations\n const dashboardVariableSelectionProviders = this.discoveryService.getProviders().filter((provider) => this.isDashboardVariableSelectionProvider(provider));\n dashboardVariableSelectionProviders.forEach((dashboardSelectionProvider) => {\n this.solidRegistry.registerDashboardVariableSelectionProvider(dashboardSelectionProvider);\n });\n\n // Register all IDashboardSelectionProvider implementations\n const dashboardQuestionDataProviders = this.discoveryService.getProviders().filter((provider) => this.isDashboardQuestionDataProvider(provider));\n dashboardQuestionDataProviders.forEach((provider) => {\n this.solidRegistry.registerDashboardQuestionDataProvider(provider);\n });\n\n // Register all IComputedProvider implementations\n const computedFieldProviders = this.discoveryService.getProviders().filter((provider) => this.isComputedFieldProvider(provider));\n computedFieldProviders.forEach((computedFieldProvider) => {\n this.solidRegistry.registerComputedFieldProvider(computedFieldProvider);\n });\n\n // Register all ISolidDatabaseModules implementations\n const solidDatabaseModules = this.discoveryService.getProviders().filter((provider) => this.isSolidDatabaseModule(provider));\n solidDatabaseModules.forEach((solidDatabaseModule) => {\n this.solidRegistry.registerSolidDatabaseModule(solidDatabaseModule);\n });\n\n // keep track of all the controllers & respective methods. \n const allControllers = this.discoveryService.getControllers().map((controller) => {\n const { instance } = controller;\n return {\n name: controller.name,\n methods: this.metadataScanner.getAllMethodNames(Object.getPrototypeOf(instance))\n };\n });\n\n this.solidRegistry.registerControllers(new Set(allControllers));\n\n // Register all modules\n const allModules = this.discoveryService.getProviders().filter((provider) => this.isModule(provider));\n this.solidRegistry.registerModules(allModules);\n\n // Register all IScheduledJob implementations\n const scheduledJobProviders = this.discoveryService.getProviders().filter((provider) => this.isScheduledJobProvider(provider));\n scheduledJobProviders.forEach((scheduledJobProvider) => {\n this.solidRegistry.registerScheduledJobProvider(scheduledJobProvider);\n });\n\n // Register all IMail implementations\n const mailProviders = this.discoveryService.getProviders().filter((provider) => this.isMailProvider(provider));\n mailProviders.forEach((mailProvider) => {\n this.solidRegistry.registerMailProvider(mailProvider);\n });\n\n // Register all IWhatsappTransport implementations\n const whatsappProviders = this.discoveryService.getProviders().filter((provider) => this.isWhatsappProvider(provider));\n whatsappProviders.forEach((whatsappProvider) => {\n this.solidRegistry.registerWhatsappProvider(whatsappProvider);\n });\n\n // Register all IWhatsappTransport implementations\n const smsProviders = this.discoveryService.getProviders().filter((provider) => this.isSmsProvider(provider));\n smsProviders.forEach((smsProvider) => {\n this.solidRegistry.registerSmsProvider(smsProvider);\n });\n\n // Register all ISecurityRuleConfigProvider implementations\n const securityRuleConfigProviders = this.discoveryService.getProviders().filter((provider) => this.isSecurityRuleConfigProvider(provider));\n securityRuleConfigProviders.forEach((securityRuleConfigProvider) => {\n this.solidRegistry.registerSecurityRuleConfigProvider(securityRuleConfigProvider);\n });\n\n // Register the core subscribers against all the configured database modules / datasources\n await this.bootstrapCoreTypeOrmSubscribers(solidDatabaseModules);\n await this.cacheAuditableModels();\n await this.settingService.updateSettingsCache();\n }\n\n private async cacheAuditableModels(): Promise<void> {\n const models = await this.modelMetadataRepo.find({\n where: { enableAuditTracking: true },\n relations: { fields: true, module: true },\n });\n\n const auditableSet = new Set<string>();\n for (const model of models) {\n const allFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName);\n const hasAuditableField = allFields.some(field =>\n field.enableAuditTracking &&\n !['mediaSingle', 'mediaMultiple', 'richText', 'json'].includes(field.type) &&\n !(field.type === 'relation' && field.relationType === 'one-to-many')\n );\n if (hasAuditableField) {\n auditableSet.add(model.singularName.toLowerCase());\n }\n }\n\n this.solidRegistry.registerAuditableModels(auditableSet);\n this.logger.debug(`Cached ${auditableSet.size} auditable model(s): ${[...auditableSet].join(', ')}`);\n }\n\n async bootstrapCoreTypeOrmSubscribers(dbModules: Array<InstanceWrapper<any>>): Promise<void> {\n // Register core subscribers for each Solid database module\n for (const wrapper of dbModules) {\n // Get the Database Module instance\n const instance = (wrapper as InstanceWrapper).instance as any;\n if (!instance || typeof instance.name !== 'function') {\n this.logger.warn('Skipping a solid DB module wrapper with no instance or name() method');\n continue;\n }\n\n // Get the DataSource for this module\n const dsName: string | undefined = instance.name();\n // getDataSourceToken() without name = default; pass dsName if non-default\n const token = dsName ? getDataSourceToken(dsName) : getDataSourceToken();\n let ds: DataSource | undefined;\n try {\n ds = this.moduleRef.get<DataSource>(token, { strict: false });\n } catch (err) {\n this.logger.warn(`DataSource token for \"${dsName ?? 'default'}\" not found: ${err?.message ?? err}`);\n }\n if (!ds) {\n this.logger.warn(`No DataSource found for module \"${dsName}\". Skipping subscriber registration.`);\n continue;\n }\n\n // Ensure DataSource is initialized (optional)\n if (!ds.isInitialized) {\n try {\n await ds.initialize(); // only if you need to initialize here; in many apps datasources are created earlier\n } catch (err) {\n this.logger.error(`Failed to initialize DataSource \"${dsName}\": ${err}`);\n continue;\n }\n }\n\n // Register each subscriber class for this DataSource\n // const auditSubscriberInstance = new AuditSubscriber(this.chatterMessageService, this.modelMetadataRepo, this.modelMetadataHelperService);\n // auditSubscriberInstance.bindToDataSource(ds);\n\n // const computedEntityFieldSubscriberInstance = new ComputedEntityFieldSubscriber(this.solidRegistry, this.publisherFactory);\n // computedEntityFieldSubscriberInstance.bindToDataSource(ds);\n\n // const createdByUpdatedBySubscriberInstance = new CreatedByUpdatedBySubscriber(this.requestContextService);\n // createdByUpdatedBySubscriberInstance.bindToDataSource(ds);\n\n // const softDeleteAwareEventSubscriberInstance = new SoftDeleteAwareEventSubscriber();\n // softDeleteAwareEventSubscriberInstance.bindToDataSource(ds);\n for (const SubClass of coreSubscriberClasses) {\n const alreadyRegistered = ds.subscribers.some(\n (s) => (s as any).constructor?.name === SubClass.name,\n );\n if (alreadyRegistered) {\n this.logger.debug(`Subscriber ${SubClass.name} already registered on datasource ${dsName ?? 'default'}`);\n continue;\n }\n\n // Resolve subscriber from NestJS moduleRef to ensure dependencies are injected\n const subscriberInstance = await this.moduleRef.resolve(SubClass, undefined, { strict: false });\n subscriberInstance.bindToDataSource(ds);\n\n // instantiate subscriber bound to this DataSource\n // NOTE: constructor signature must be (dataSource: DataSource, requestContextService: RequestContextService, ...)\n // const subscriberInstance = new (SubClass as any)(ds, this.requestContextService);\n\n // ds.subscribers.push(subscriberInstance);\n // this.logger.log(`Registered subscriber ${SubClass.name} on datasource ${dsName ?? 'default'}`);\n }\n }\n }\n\n isDashboardQuestionDataProvider(providerWrapper: InstanceWrapper<any>) {\n const { instance } = providerWrapper;\n if (!instance) return false;\n const provider = this.reflector.get<boolean>(\n IS_DASHBOARD_QUESTION_DATA_PROVIDER,\n instance.constructor,\n );\n return !!provider;\n }\n\n // This method identifies a provider as a seeder if it has a seed method i.e duck typing\n private isSeeder(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const seedMethod = this.metadataScanner.getAllMethodNames(Object.getPrototypeOf(instance)).find((methodName) => methodName === 'seed');\n if (!seedMethod) return false;\n return true;\n }\n\n private isErrorCodeProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isErrorCodeProvider = this.reflector.get<boolean>(\n IS_ERROR_CODE_PROVIDER,\n instance.constructor,\n );\n\n return !!isErrorCodeProvider;\n }\n\n private isSelectionProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSelectionProvider = this.reflector.get<boolean>(\n IS_SELECTION_PROVIDER,\n instance.constructor,\n );\n\n return !!isSelectionProvider;\n }\n\n private isSettingsProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSettingsProvider = this.reflector.get<boolean>(\n IS_SETTINGS_PROVIDER,\n instance.constructor,\n );\n\n return !!isSettingsProvider;\n }\n\n private isDashboardVariableSelectionProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n const isDashboardSelectionProvider = this.reflector.get<boolean>(\n IS_DASHBOARD_VARIABLE_SELECTION_PROVIDER,\n instance.constructor,\n );\n return !!isDashboardSelectionProvider;\n }\n\n private isComputedFieldProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isComputedFieldProvider = this.reflector.get<boolean>(\n IS_COMPUTED_FIELD_PROVIDER,\n instance.constructor,\n );\n\n return !!isComputedFieldProvider;\n }\n\n private isScheduledJobProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isScheduledJobProvider = this.reflector.get<boolean>(\n IS_SCHEDULED_JOB_PROVIDER,\n instance.constructor,\n );\n\n return !!isScheduledJobProvider;\n }\n\n private isSolidDatabaseModule(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSolidDatabaseModule = this.reflector.get<boolean>(\n IS_SOLID_DATABASE_MODULE,\n instance.constructor,\n );\n\n return !!isSolidDatabaseModule;\n }\n\n private isMailProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isMailProvider = this.reflector.get<boolean>(\n IS_MAIL_PROVIDER,\n instance.constructor,\n );\n\n return !!isMailProvider;\n }\n\n private isWhatsappProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isWhatsappProvider = this.reflector.get<boolean>(\n IS_WA_PROVIDER,\n instance.constructor,\n );\n\n return !!isWhatsappProvider;\n }\n\n private isSmsProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSmsProvider = this.reflector.get<boolean>(\n IS_SMS_PROVIDER,\n instance.constructor,\n );\n\n return !!isSmsProvider;\n }\n\n private isSecurityRuleConfigProvider(provider: InstanceWrapper) {\n const { instance } = provider;\n if (!instance) return false;\n\n const isSecurityRuleConfigProvider = this.reflector.get<boolean>(\n IS_SECURITY_RULE_CONFIG_PROVIDER,\n instance.constructor,\n );\n\n return !!isSecurityRuleConfigProvider;\n }\n\n private isModule(provider: InstanceWrapper): boolean {\n const metatype = provider.metatype;\n // Check if it's a Static Module (Class-Based)\n if (metatype && typeof metatype === 'function' && Reflect.getMetadata('imports', metatype)) {\n return true;\n }\n\n // Ensure provider.instance is an object before checking for 'module'\n if (provider.instance && typeof provider.instance === 'object') {\n // Check if it's a Dynamic Module (Object-Based)\n if ('module' in provider.instance && typeof provider.instance.module === 'function') {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Given a model singular name this will return the crud service instance.\n * @param modelSingularName \n * @returns \n */\n getCRUDService(modelSingularName: string): CRUDService<any> {\n const provider = this.getProvider(`${classify(modelSingularName)}Service`);\n return provider?.instance as CRUDService<any>;\n }\n\n getProvider(providerName: string) {\n return this.discoveryService.getProviders().find((provider) => provider.name === providerName);\n }\n}\n"]}
@@ -1,13 +1,11 @@
1
- import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
2
- import { ModelMetadataRepository } from 'src/repository/model-metadata.repository';
1
+ import { SolidRegistry } from 'src/helpers/solid-registry';
3
2
  import { DataSource, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';
4
3
  import { ChatterMessageService } from '../services/chatter-message.service';
5
4
  export declare class AuditSubscriber implements EntitySubscriberInterface {
6
5
  private readonly chatterMessageService;
7
- private readonly modelMetadataRepo;
8
- private readonly modelMetadataHelperService;
6
+ private readonly solidRegistry;
9
7
  private dataSource;
10
- constructor(chatterMessageService: ChatterMessageService, modelMetadataRepo: ModelMetadataRepository, modelMetadataHelperService: ModelMetadataHelperService);
8
+ constructor(chatterMessageService: ChatterMessageService, solidRegistry: SolidRegistry);
11
9
  bindToDataSource(dataSource: DataSource): void;
12
10
  private perTxn;
13
11
  private enqueue;
@@ -1 +1 @@
1
- {"version":3,"file":"audit.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/audit.subscriber.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAEvF,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,EAAE,UAAU,EAAkB,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvH,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAQ5E,qBAEa,eAAgB,YAAW,yBAAyB;IAKzD,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAItC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,0BAA0B;IAT/C,OAAO,CAAC,UAAU,CAAa;gBAIV,qBAAqB,EAAE,qBAAqB,EAI5C,iBAAiB,EAAE,uBAAuB,EAC1C,0BAA0B,EAAE,0BAA0B;IAK3E,gBAAgB,CAAC,UAAU,EAAE,UAAU;IAMvC,OAAO,CAAC,MAAM,CAAsC;IAEpD,OAAO,CAAC,OAAO;YAOD,gBAAgB;IAsCxB,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAUnC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAenC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAenC,sBAAsB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,GAAG,CAAA;KAAE;IAmBxD,wBAAwB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,GAAG,CAAA;KAAE;CAIvD"}
1
+ {"version":3,"file":"audit.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/audit.subscriber.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAkB,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACvH,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAQ5E,qBAEa,eAAgB,YAAW,yBAAyB;IAGzD,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAHlC,OAAO,CAAC,UAAU,CAAa;gBAEV,qBAAqB,EAAE,qBAAqB,EAC5C,aAAa,EAAE,aAAa;IAGjD,gBAAgB,CAAC,UAAU,EAAE,UAAU;IAMvC,OAAO,CAAC,MAAM,CAAsC;IAEpD,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,gBAAgB;IAIlB,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAUnC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAenC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAenC,sBAAsB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,GAAG,CAAA;KAAE;IAmBxD,wBAAwB,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,GAAG,CAAA;KAAE;CAIvD"}
@@ -8,21 +8,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
10
  };
11
- var __param = (this && this.__param) || function (paramIndex, decorator) {
12
- return function (target, key) { decorator(target, key, paramIndex); }
13
- };
14
11
  Object.defineProperty(exports, "__esModule", { value: true });
15
12
  exports.AuditSubscriber = void 0;
16
13
  const common_1 = require("@nestjs/common");
17
- const model_metadata_helper_service_1 = require("../helpers/model-metadata-helper.service");
18
14
  const string_helper_1 = require("../helpers/string.helper");
19
- const model_metadata_repository_1 = require("../repository/model-metadata.repository");
15
+ const solid_registry_1 = require("../helpers/solid-registry");
20
16
  const chatter_message_service_1 = require("../services/chatter-message.service");
21
17
  let AuditSubscriber = class AuditSubscriber {
22
- constructor(chatterMessageService, modelMetadataRepo, modelMetadataHelperService) {
18
+ constructor(chatterMessageService, solidRegistry) {
23
19
  this.chatterMessageService = chatterMessageService;
24
- this.modelMetadataRepo = modelMetadataRepo;
25
- this.modelMetadataHelperService = modelMetadataHelperService;
20
+ this.solidRegistry = solidRegistry;
26
21
  this.perTxn = new WeakMap();
27
22
  }
28
23
  bindToDataSource(dataSource) {
@@ -35,33 +30,11 @@ let AuditSubscriber = class AuditSubscriber {
35
30
  arr.push(call);
36
31
  this.perTxn.set(qr, arr);
37
32
  }
38
- async shouldTrackAudit(entity, metadata) {
39
- const model = await this.modelMetadataRepo.findOne({
40
- where: {
41
- singularName: (0, string_helper_1.lowerFirst)(metadata.name)
42
- },
43
- relations: {
44
- fields: true,
45
- module: true
46
- }
47
- });
48
- if (!model || !model.enableAuditTracking) {
49
- return false;
50
- }
51
- const modelFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName);
52
- const auditFields = modelFields.filter(field => field.enableAuditTracking &&
53
- !['mediaSingle', 'mediaMultiple', 'richText', 'json'].includes(field.type) &&
54
- !(field.type === 'relation' && field.relationType === 'one-to-many'));
55
- if (auditFields.length === 0) {
56
- return false;
57
- }
58
- return entity && auditFields.some(field => {
59
- const fieldValue = entity[field.name];
60
- return fieldValue !== undefined && fieldValue !== null;
61
- });
33
+ shouldTrackAudit(metadata) {
34
+ return this.solidRegistry.isAuditableModel((0, string_helper_1.lowerFirst)(metadata.name));
62
35
  }
63
36
  async afterInsert(event) {
64
- if (await this.shouldTrackAudit(event.entity, event.metadata)) {
37
+ if (this.shouldTrackAudit(event.metadata)) {
65
38
  this.enqueue(event, {
66
39
  kind: 'insert',
67
40
  args: [event.entity, event.metadata],
@@ -69,7 +42,7 @@ let AuditSubscriber = class AuditSubscriber {
69
42
  }
70
43
  }
71
44
  async afterUpdate(event) {
72
- if (await this.shouldTrackAudit(event.entity, event.metadata)) {
45
+ if (this.shouldTrackAudit(event.metadata)) {
73
46
  this.enqueue(event, {
74
47
  kind: 'update',
75
48
  args: [
@@ -82,7 +55,7 @@ let AuditSubscriber = class AuditSubscriber {
82
55
  }
83
56
  }
84
57
  async afterRemove(event) {
85
- if (await this.shouldTrackAudit(event.entity, event.metadata)) {
58
+ if (this.shouldTrackAudit(event.metadata)) {
86
59
  this.enqueue(event, {
87
60
  kind: 'delete',
88
61
  args: [
@@ -121,9 +94,7 @@ let AuditSubscriber = class AuditSubscriber {
121
94
  exports.AuditSubscriber = AuditSubscriber;
122
95
  exports.AuditSubscriber = AuditSubscriber = __decorate([
123
96
  (0, common_1.Injectable)({ scope: common_1.Scope.TRANSIENT }),
124
- __param(1, (0, common_1.Inject)((0, common_1.forwardRef)(() => model_metadata_repository_1.ModelMetadataRepository))),
125
97
  __metadata("design:paramtypes", [chatter_message_service_1.ChatterMessageService,
126
- model_metadata_repository_1.ModelMetadataRepository,
127
- model_metadata_helper_service_1.ModelMetadataHelperService])
98
+ solid_registry_1.SolidRegistry])
128
99
  ], AuditSubscriber);
129
100
  //# sourceMappingURL=audit.subscriber.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/audit.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { forwardRef, Inject, Injectable, Scope } from '@nestjs/common';\nimport { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\nimport { lowerFirst } from 'src/helpers/string.helper';\nimport { ModelMetadataRepository } from 'src/repository/model-metadata.repository';\nimport { DataSource, EntityMetadata, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';\nimport { ChatterMessageService } from '../services/chatter-message.service';\n\n\ntype DeferredCall =\n | { kind: 'insert'; args: Parameters<ChatterMessageService['postAuditMessageOnInsert']> }\n | { kind: 'update'; args: Parameters<ChatterMessageService['postAuditMessageOnUpdate']> }\n | { kind: 'delete'; args: Parameters<ChatterMessageService['postAuditMessageOnDelete']> };\n\n@Injectable({scope: Scope.TRANSIENT})\n// @EventSubscriber()\nexport class AuditSubscriber implements EntitySubscriberInterface {\n private dataSource: DataSource;\n constructor(\n // @InjectDataSource()\n // private readonly dataSource: DataSource,\n private readonly chatterMessageService: ChatterMessageService,\n // @InjectRepository(ModelMetadata)\n // private readonly modelMetadataRepo: Repository<ModelMetadata>,\n @Inject(forwardRef(() => ModelMetadataRepository))\n private readonly modelMetadataRepo: ModelMetadataRepository,\n private readonly modelMetadataHelperService: ModelMetadataHelperService,\n ) {\n // this.dataSource.subscribers.push(this);\n }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n // Per-transaction buffer (auto-GC when queryRunner is gone)\n private perTxn = new WeakMap<any, DeferredCall[]>();\n\n private enqueue(event: { queryRunner: any }, call: DeferredCall) {\n const qr = event.queryRunner;\n const arr = this.perTxn.get(qr) ?? [];\n arr.push(call);\n this.perTxn.set(qr, arr);\n }\n\n private async shouldTrackAudit(entity: any, metadata: EntityMetadata): Promise<boolean> {\n const model = await this.modelMetadataRepo.findOne({\n where: {\n singularName: lowerFirst(metadata.name)\n },\n relations: {\n fields: true,\n module: true\n }\n });\n\n if (!model || !model.enableAuditTracking) {\n return false;\n }\n\n const modelFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName)\n\n const auditFields = modelFields.filter(field =>\n field.enableAuditTracking &&\n !['mediaSingle', 'mediaMultiple', 'richText', 'json'].includes(field.type) &&\n !(field.type === 'relation' && field.relationType === 'one-to-many')\n );\n\n if (auditFields.length === 0) {\n return false;\n }\n\n // if (!entity) {\n // console.warn(`[AuditSubscriber] Skipping audit for ${metadata.name} – entity is undefined or null`);\n // return false;\n // }\n\n return entity && auditFields.some(field => {\n const fieldValue = entity[field.name];\n return fieldValue !== undefined && fieldValue !== null;\n });\n }\n\n async afterInsert(event: InsertEvent<any>) {\n if (await this.shouldTrackAudit(event.entity, event.metadata)) {\n // await this.chatterMessageService.postAuditMessageOnInsert(event.entity, event.metadata);\n this.enqueue(event, {\n kind: 'insert',\n args: [event.entity, event.metadata] as Parameters<ChatterMessageService['postAuditMessageOnInsert']>,\n });\n }\n }\n\n async afterUpdate(event: UpdateEvent<any>) {\n if (await this.shouldTrackAudit(event.entity, event.metadata)) {\n // await this.chatterMessageService.postAuditMessageOnUpdate(event.entity, event.metadata, event.databaseEntity, event.updatedColumns || []);\n this.enqueue(event, {\n kind: 'update',\n args: [\n event.entity, // entity (after)\n event.metadata,\n event.databaseEntity, // entity (before)\n event.updatedColumns ?? [],\n ] as Parameters<ChatterMessageService['postAuditMessageOnUpdate']>,\n });\n }\n }\n\n async afterRemove(event: RemoveEvent<any>) {\n if (await this.shouldTrackAudit(event.entity, event.metadata)) {\n // await this.chatterMessageService.postAuditMessageOnDelete(event.entity, event.metadata, event.databaseEntity);\n this.enqueue(event, {\n kind: 'delete',\n args: [\n event.entity,\n event.metadata,\n event.databaseEntity,\n ] as Parameters<ChatterMessageService['postAuditMessageOnDelete']>,\n });\n }\n }\n\n // --------- transaction lifecycle ----------\n async afterTransactionCommit(event: { queryRunner: any }) {\n const batch = this.perTxn.get(event.queryRunner) ?? [];\n this.perTxn.delete(event.queryRunner);\n\n // Now we’re OUTSIDE the DB transaction — safe to do I/O/DB writes inside chatter service.\n for (const item of batch) {\n try {\n switch (item.kind) {\n case 'insert': await this.chatterMessageService.postAuditMessageOnInsert(...item.args); break;\n case 'update': await this.chatterMessageService.postAuditMessageOnUpdate(...item.args); break;\n case 'delete': await this.chatterMessageService.postAuditMessageOnDelete(...item.args); break;\n }\n } catch (e) {\n // Best effort: log and continue; your core txn was already committed\n // Optionally: send to a generic error logger/metric here\n }\n }\n }\n\n afterTransactionRollback(event: { queryRunner: any }) {\n // Drop buffered calls; the write never happened\n this.perTxn.delete(event.queryRunner);\n }\n}\n\n// import { DataSource, EntityMetadata, EntitySubscriberInterface, EventSubscriber, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';\n// import { Injectable } from '@nestjs/common';\n// import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';\n// import { Repository } from 'typeorm';\n// import { ModelMetadata } from '../entities/model-metadata.entity';\n// import { lowerFirst } from 'src/helpers/string.helper';\n// import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\n// import { ChatterMessagePayload } from 'src/jobs/chatter-queue-publisher.service';\n// import { RequestContextService } from 'src/services/request-context.service';\n// import { PublisherFactory } from 'src/services/queues/publisher-factory.service';\n\n// @EventSubscriber()\n// @Injectable()\n// export class AuditSubscriber implements EntitySubscriberInterface {\n// private perTxn = new WeakMap<any, ChatterMessagePayload[]>();\n\n// constructor(\n// @InjectDataSource() private readonly dataSource: DataSource,\n// @InjectRepository(ModelMetadata) private readonly modelMetadataRepo: Repository<ModelMetadata>,\n// private readonly modelMetadataHelperService: ModelMetadataHelperService,\n// private readonly requestContext: RequestContextService,\n// private readonly publisherFactory: PublisherFactory<any>\n// ) {\n// this.dataSource.subscribers.push(this);\n// }\n\n// // --- small cache to avoid metadata queries on every row ---\n// private modelCache = new Map<string, { enable: boolean; fields: Array<{ name: string; enableAuditTracking: boolean; type: string; relationType?: string }>; ts: number }>();\n// private cacheTTLms = 60_000;\n\n// private async shouldTrackAudit(entity: any, metadata: EntityMetadata): Promise<{ enable: boolean; auditFields?: string[] }> {\n// const key = metadata.name;\n// const now = Date.now();\n// const cached = this.modelCache.get(key);\n// if (cached && (now - cached.ts) < this.cacheTTLms) {\n// if (!cached.enable) return { enable: false };\n// const fields = cached.fields.filter(f =>\n// f.enableAuditTracking &&\n// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&\n// !(f.type === 'relation' && f.relationType === 'one-to-many')\n// );\n// const present = fields.map(f => f.name).filter(n => entity?.[n] !== undefined);\n// return { enable: present.length > 0, auditFields: present };\n// }\n\n// const model = await this.modelMetadataRepo.findOne({\n// where: { singularName: lowerFirst(metadata.name) },\n// relations: { fields: true, module: true },\n// });\n// const enable = !!model?.enableAuditTracking;\n// const fields = model?.fields ?? [];\n// this.modelCache.set(key, { enable, fields, ts: now });\n\n// if (!enable) return { enable: false };\n// const filtered = fields.filter(f =>\n// f.enableAuditTracking &&\n// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&\n// !(f.type === 'relation' && f.relationType === 'one-to-many')\n// );\n// const present = filtered.map(f => f.name).filter(n => entity?.[n] !== undefined);\n// return { enable: present.length > 0, auditFields: present };\n// }\n\n// private push(event: { queryRunner: any }, msg: ChatterMessagePayload) {\n// const arr = this.perTxn.get(event.queryRunner) ?? [];\n// arr.push(msg);\n// this.perTxn.set(event.queryRunner, arr);\n// }\n\n// async afterInsert(event: InsertEvent<any>) {\n// if (!event.entity) return;\n// const enable = await this.shouldTrackAudit(event.entity, event.metadata);\n// if (!enable) return;\n\n// const payload: ChatterMessagePayload = {\n// eventType: 'insert',\n// model: event.metadata.name,\n// entityId: String(event.entity.id ?? event.entity.uuid ?? ''),\n// occurredAt: new Date().toISOString(),\n// after: this.safeCopy(event.entity),\n// userId: this.getUserId(),\n// };\n// this.push(event, payload);\n// }\n\n// async afterUpdate(event: UpdateEvent<any>) {\n// // Updated entity may be null if you used raw query; fall back to databaseEntity\n// const current = event.entity ?? {};\n// const before = event.databaseEntity ?? {};\n// const { enable, auditFields } = await this.shouldTrackAudit(current, event.metadata);\n// if (!enable) return;\n\n// const changedCols = (event.updatedColumns || []).map(c => c.propertyName);\n// const payload: ChatterMessagePayload = {\n// eventType: 'update',\n// model: event.metadata.name,\n// entityId: String((current as any).id ?? (before as any).id ?? ''),\n// occurredAt: new Date().toISOString(),\n// before: this.pick(before, auditFields || changedCols),\n// after: this.pick(current, auditFields || changedCols),\n// diff: changedCols,\n// userId: this.getUserId(),\n// };\n// this.push(event, payload);\n// }\n\n// async afterRemove(event: RemoveEvent<any>) {\n// const base = event.entity ?? event.databaseEntity;\n// if (!base) return;\n\n// const { enable } = await this.shouldTrackAudit(base, event.metadata);\n// if (!enable) return;\n\n// const payload: ChatterMessagePayload = {\n// eventType: 'delete',\n// model: event.metadata.name,\n// entityId: String((base as any).id ?? ''),\n// occurredAt: new Date().toISOString(),\n// before: this.safeCopy(base),\n// userId: this.getUserId(),\n// };\n// this.push(event, payload);\n// }\n\n// // Publish AFTER the transaction commits -> no idle-in-transaction\n// async afterTransactionCommit(event: { queryRunner: any }) {\n// const batch = this.perTxn.get(event.queryRunner) ?? [];\n// this.perTxn.delete(event.queryRunner);\n// for (const msg of batch) {\n// try {\n// await this.publisherFactory.publish({ payload: msg, parentEntity: msg.model, parentEntityId: msg.entityId }, 'ChatterQueuePublisher');\n// } catch (err) {\n// // log + optionally send to a DLQ or retry queue\n// // do NOT throw; commit already happened\n// // your RabbitMqPublisher likely tracks failures in MqMessage tables anyway\n// }\n// }\n// }\n\n// afterTransactionRollback(event: { queryRunner: any }) {\n// this.perTxn.delete(event.queryRunner);\n// }\n\n// // --- small helpers to keep payloads JSON-safe and small ---\n// private safeCopy(obj: any) {\n// try {\n// return JSON.parse(JSON.stringify(obj));\n// } catch {\n// return {}; // strip circular refs\n// }\n// }\n\n// private pick(obj: any, keys: string[]) {\n// const out: any = {};\n// for (const k of keys) out[k] = obj?.[k];\n// return this.safeCopy(out);\n// }\n\n// private getUserId(): string | null {\n\n// const activeUser = this.requestContext.getActiveUser();\n// if (activeUser?.sub)\n// return String(activeUser.sub);\n// }\n\n\n// }"]}
1
+ {"version":3,"file":"audit.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/audit.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Scope } from '@nestjs/common';\nimport { lowerFirst } from 'src/helpers/string.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { DataSource, EntityMetadata, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';\nimport { ChatterMessageService } from '../services/chatter-message.service';\n\n\ntype DeferredCall =\n | { kind: 'insert'; args: Parameters<ChatterMessageService['postAuditMessageOnInsert']> }\n | { kind: 'update'; args: Parameters<ChatterMessageService['postAuditMessageOnUpdate']> }\n | { kind: 'delete'; args: Parameters<ChatterMessageService['postAuditMessageOnDelete']> };\n\n@Injectable({scope: Scope.TRANSIENT})\n// @EventSubscriber()\nexport class AuditSubscriber implements EntitySubscriberInterface {\n private dataSource: DataSource;\n constructor(\n private readonly chatterMessageService: ChatterMessageService,\n private readonly solidRegistry: SolidRegistry,\n ) { }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n // Per-transaction buffer (auto-GC when queryRunner is gone)\n private perTxn = new WeakMap<any, DeferredCall[]>();\n\n private enqueue(event: { queryRunner: any }, call: DeferredCall) {\n const qr = event.queryRunner;\n const arr = this.perTxn.get(qr) ?? [];\n arr.push(call);\n this.perTxn.set(qr, arr);\n }\n\n private shouldTrackAudit(metadata: EntityMetadata): boolean {\n return this.solidRegistry.isAuditableModel(lowerFirst(metadata.name));\n }\n\n async afterInsert(event: InsertEvent<any>) {\n if (this.shouldTrackAudit(event.metadata)) {\n // await this.chatterMessageService.postAuditMessageOnInsert(event.entity, event.metadata);\n this.enqueue(event, {\n kind: 'insert',\n args: [event.entity, event.metadata] as Parameters<ChatterMessageService['postAuditMessageOnInsert']>,\n });\n }\n }\n\n async afterUpdate(event: UpdateEvent<any>) {\n if (this.shouldTrackAudit(event.metadata)) {\n // await this.chatterMessageService.postAuditMessageOnUpdate(event.entity, event.metadata, event.databaseEntity, event.updatedColumns || []);\n this.enqueue(event, {\n kind: 'update',\n args: [\n event.entity, // entity (after)\n event.metadata,\n event.databaseEntity, // entity (before)\n event.updatedColumns ?? [],\n ] as Parameters<ChatterMessageService['postAuditMessageOnUpdate']>,\n });\n }\n }\n\n async afterRemove(event: RemoveEvent<any>) {\n if (this.shouldTrackAudit(event.metadata)) {\n // await this.chatterMessageService.postAuditMessageOnDelete(event.entity, event.metadata, event.databaseEntity);\n this.enqueue(event, {\n kind: 'delete',\n args: [\n event.entity,\n event.metadata,\n event.databaseEntity,\n ] as Parameters<ChatterMessageService['postAuditMessageOnDelete']>,\n });\n }\n }\n\n // --------- transaction lifecycle ----------\n async afterTransactionCommit(event: { queryRunner: any }) {\n const batch = this.perTxn.get(event.queryRunner) ?? [];\n this.perTxn.delete(event.queryRunner);\n\n // Now we’re OUTSIDE the DB transaction — safe to do I/O/DB writes inside chatter service.\n for (const item of batch) {\n try {\n switch (item.kind) {\n case 'insert': await this.chatterMessageService.postAuditMessageOnInsert(...item.args); break;\n case 'update': await this.chatterMessageService.postAuditMessageOnUpdate(...item.args); break;\n case 'delete': await this.chatterMessageService.postAuditMessageOnDelete(...item.args); break;\n }\n } catch (e) {\n // Best effort: log and continue; your core txn was already committed\n // Optionally: send to a generic error logger/metric here\n }\n }\n }\n\n afterTransactionRollback(event: { queryRunner: any }) {\n // Drop buffered calls; the write never happened\n this.perTxn.delete(event.queryRunner);\n }\n}\n\n// import { DataSource, EntityMetadata, EntitySubscriberInterface, EventSubscriber, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';\n// import { Injectable } from '@nestjs/common';\n// import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';\n// import { Repository } from 'typeorm';\n// import { ModelMetadata } from '../entities/model-metadata.entity';\n// import { lowerFirst } from 'src/helpers/string.helper';\n// import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\n// import { ChatterMessagePayload } from 'src/jobs/chatter-queue-publisher.service';\n// import { RequestContextService } from 'src/services/request-context.service';\n// import { PublisherFactory } from 'src/services/queues/publisher-factory.service';\n\n// @EventSubscriber()\n// @Injectable()\n// export class AuditSubscriber implements EntitySubscriberInterface {\n// private perTxn = new WeakMap<any, ChatterMessagePayload[]>();\n\n// constructor(\n// @InjectDataSource() private readonly dataSource: DataSource,\n// @InjectRepository(ModelMetadata) private readonly modelMetadataRepo: Repository<ModelMetadata>,\n// private readonly modelMetadataHelperService: ModelMetadataHelperService,\n// private readonly requestContext: RequestContextService,\n// private readonly publisherFactory: PublisherFactory<any>\n// ) {\n// this.dataSource.subscribers.push(this);\n// }\n\n// // --- small cache to avoid metadata queries on every row ---\n// private modelCache = new Map<string, { enable: boolean; fields: Array<{ name: string; enableAuditTracking: boolean; type: string; relationType?: string }>; ts: number }>();\n// private cacheTTLms = 60_000;\n\n// private async shouldTrackAudit(entity: any, metadata: EntityMetadata): Promise<{ enable: boolean; auditFields?: string[] }> {\n// const key = metadata.name;\n// const now = Date.now();\n// const cached = this.modelCache.get(key);\n// if (cached && (now - cached.ts) < this.cacheTTLms) {\n// if (!cached.enable) return { enable: false };\n// const fields = cached.fields.filter(f =>\n// f.enableAuditTracking &&\n// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&\n// !(f.type === 'relation' && f.relationType === 'one-to-many')\n// );\n// const present = fields.map(f => f.name).filter(n => entity?.[n] !== undefined);\n// return { enable: present.length > 0, auditFields: present };\n// }\n\n// const model = await this.modelMetadataRepo.findOne({\n// where: { singularName: lowerFirst(metadata.name) },\n// relations: { fields: true, module: true },\n// });\n// const enable = !!model?.enableAuditTracking;\n// const fields = model?.fields ?? [];\n// this.modelCache.set(key, { enable, fields, ts: now });\n\n// if (!enable) return { enable: false };\n// const filtered = fields.filter(f =>\n// f.enableAuditTracking &&\n// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&\n// !(f.type === 'relation' && f.relationType === 'one-to-many')\n// );\n// const present = filtered.map(f => f.name).filter(n => entity?.[n] !== undefined);\n// return { enable: present.length > 0, auditFields: present };\n// }\n\n// private push(event: { queryRunner: any }, msg: ChatterMessagePayload) {\n// const arr = this.perTxn.get(event.queryRunner) ?? [];\n// arr.push(msg);\n// this.perTxn.set(event.queryRunner, arr);\n// }\n\n// async afterInsert(event: InsertEvent<any>) {\n// if (!event.entity) return;\n// const enable = await this.shouldTrackAudit(event.entity, event.metadata);\n// if (!enable) return;\n\n// const payload: ChatterMessagePayload = {\n// eventType: 'insert',\n// model: event.metadata.name,\n// entityId: String(event.entity.id ?? event.entity.uuid ?? ''),\n// occurredAt: new Date().toISOString(),\n// after: this.safeCopy(event.entity),\n// userId: this.getUserId(),\n// };\n// this.push(event, payload);\n// }\n\n// async afterUpdate(event: UpdateEvent<any>) {\n// // Updated entity may be null if you used raw query; fall back to databaseEntity\n// const current = event.entity ?? {};\n// const before = event.databaseEntity ?? {};\n// const { enable, auditFields } = await this.shouldTrackAudit(current, event.metadata);\n// if (!enable) return;\n\n// const changedCols = (event.updatedColumns || []).map(c => c.propertyName);\n// const payload: ChatterMessagePayload = {\n// eventType: 'update',\n// model: event.metadata.name,\n// entityId: String((current as any).id ?? (before as any).id ?? ''),\n// occurredAt: new Date().toISOString(),\n// before: this.pick(before, auditFields || changedCols),\n// after: this.pick(current, auditFields || changedCols),\n// diff: changedCols,\n// userId: this.getUserId(),\n// };\n// this.push(event, payload);\n// }\n\n// async afterRemove(event: RemoveEvent<any>) {\n// const base = event.entity ?? event.databaseEntity;\n// if (!base) return;\n\n// const { enable } = await this.shouldTrackAudit(base, event.metadata);\n// if (!enable) return;\n\n// const payload: ChatterMessagePayload = {\n// eventType: 'delete',\n// model: event.metadata.name,\n// entityId: String((base as any).id ?? ''),\n// occurredAt: new Date().toISOString(),\n// before: this.safeCopy(base),\n// userId: this.getUserId(),\n// };\n// this.push(event, payload);\n// }\n\n// // Publish AFTER the transaction commits -> no idle-in-transaction\n// async afterTransactionCommit(event: { queryRunner: any }) {\n// const batch = this.perTxn.get(event.queryRunner) ?? [];\n// this.perTxn.delete(event.queryRunner);\n// for (const msg of batch) {\n// try {\n// await this.publisherFactory.publish({ payload: msg, parentEntity: msg.model, parentEntityId: msg.entityId }, 'ChatterQueuePublisher');\n// } catch (err) {\n// // log + optionally send to a DLQ or retry queue\n// // do NOT throw; commit already happened\n// // your RabbitMqPublisher likely tracks failures in MqMessage tables anyway\n// }\n// }\n// }\n\n// afterTransactionRollback(event: { queryRunner: any }) {\n// this.perTxn.delete(event.queryRunner);\n// }\n\n// // --- small helpers to keep payloads JSON-safe and small ---\n// private safeCopy(obj: any) {\n// try {\n// return JSON.parse(JSON.stringify(obj));\n// } catch {\n// return {}; // strip circular refs\n// }\n// }\n\n// private pick(obj: any, keys: string[]) {\n// const out: any = {};\n// for (const k of keys) out[k] = obj?.[k];\n// return this.safeCopy(out);\n// }\n\n// private getUserId(): string | null {\n\n// const activeUser = this.requestContext.getActiveUser();\n// if (activeUser?.sub)\n// return String(activeUser.sub);\n// }\n\n\n// }"]}
@@ -0,0 +1,49 @@
1
+ [2026-04-01T11:32:43.795Z] ERROR: [200 OK] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly 59891ms
2
+ [2026-04-01T11:32:43.795Z] ERROR: [500 Internal Server Error] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly [code=solidx-unknown-error]
3
+ [2026-04-01T11:32:43.795Z] ERROR: QueryFailedError: Connection terminated unexpectedly
4
+ at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
5
+ at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
6
+ at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
7
+ at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
8
+ at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
9
+ at async SelectQueryBuilder.getOne (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1698:25)
10
+ at async AuthenticationService.findUserForLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:725:22)
11
+ at async AuthenticationService.otpConfirmLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:821:22)
12
+ [2026-04-01T11:32:43.796Z] ERROR: [200 OK] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly 59912ms
13
+ [2026-04-01T11:32:43.796Z] ERROR: [500 Internal Server Error] POST /api/iam/otp/login/confirm - Connection terminated unexpectedly [code=solidx-unknown-error]
14
+ [2026-04-01T11:32:43.796Z] ERROR: QueryFailedError: Connection terminated unexpectedly
15
+ at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
16
+ at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
17
+ at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
18
+ at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
19
+ at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
20
+ at async SelectQueryBuilder.getOne (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1698:25)
21
+ at async AuthenticationService.findUserForLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:725:22)
22
+ at async AuthenticationService.otpConfirmLogin (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/services/authentication.service.ts:821:22)
23
+ [2026-04-01T11:32:43.797Z] ERROR: [500 Internal Server Error] POST /api/lead - Connection terminated unexpectedly [code=solidx-unknown-error]
24
+ [2026-04-01T11:32:43.797Z] ERROR: QueryFailedError: Connection terminated unexpectedly
25
+ at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
26
+ at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
27
+ at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
28
+ at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
29
+ at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
30
+ at async SelectQueryBuilder.getMany (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1761:25)
31
+ at async AuthenticationGuard.canActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/guards/authentication.guard.ts:55:36)
32
+ at async GuardsConsumer.tryActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/guards/guards-consumer.js:16:17)
33
+ at async canActivateFn (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:135:33)
34
+ at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:42:31
35
+ at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-proxy.js:9:17
36
+ [2026-04-01T11:32:43.798Z] ERROR: [500 Internal Server Error] POST /api/lead - Connection terminated unexpectedly [code=solidx-unknown-error]
37
+ [2026-04-01T11:32:43.798Z] ERROR: QueryFailedError: Connection terminated unexpectedly
38
+ at PostgresQueryRunner.query (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/driver/src/driver/postgres/PostgresQueryRunner.ts:325:19)
39
+ at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
40
+ at async SelectQueryBuilder.loadRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3868:25)
41
+ at async SelectQueryBuilder.executeEntitiesAndRawResults (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:3614:26)
42
+ at async SelectQueryBuilder.getRawAndEntities (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1671:29)
43
+ at async SelectQueryBuilder.getMany (/opt/gitco/rnlic-venue-app/solid-api/node_modules/typeorm/query-builder/src/query-builder/SelectQueryBuilder.ts:1761:25)
44
+ at async AuthenticationGuard.canActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@solidxai/core/src/guards/authentication.guard.ts:55:36)
45
+ at async GuardsConsumer.tryActivate (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/guards/guards-consumer.js:16:17)
46
+ at async canActivateFn (/opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:135:33)
47
+ at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-execution-context.js:42:31
48
+ at async /opt/gitco/rnlic-venue-app/solid-api/node_modules/@nestjs/core/router/router-proxy.js:9:17
49
+ [2026-04-01T11:32:43.799Z] ERROR: [500 Internal Server Error] POST /api/lead - Connection terminated unexpectedly [code=solidx-unknown-error]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidxai/core",
3
- "version": "0.1.6-beta.21",
3
+ "version": "0.1.6-beta.23",
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",
@@ -82,6 +82,7 @@ export class SolidRegistry {
82
82
  private securityRuleConfigProviders: Set<InstanceWrapper> = new Set();
83
83
  private errorCodeProviders: Set<InstanceWrapper> = new Set();
84
84
  private settingsProviders: Set<InstanceWrapper> = new Set();
85
+ private auditableModels: Set<string> = new Set();
85
86
 
86
87
  registerErrorCodeProvider(errorCodeProvider: InstanceWrapper): void {
87
88
  this.errorCodeProviders.add(errorCodeProvider);
@@ -338,6 +339,14 @@ export class SolidRegistry {
338
339
  });
339
340
  }
340
341
 
342
+ registerAuditableModels(models: Set<string>): void {
343
+ this.auditableModels = models;
344
+ }
345
+
346
+ isAuditableModel(modelSingularName: string): boolean {
347
+ return this.auditableModels.has(modelSingularName.toLowerCase());
348
+ }
349
+
341
350
  getCommonEntityKeys(): (keyof CommonEntity | 'createdBy' | 'updatedBy')[] {
342
351
  return ['id', 'createdAt', 'updatedAt', 'deletedAt', 'createdBy', 'updatedBy', 'deletedTracker', 'localeName', 'defaultEntityLocaleId', 'publishedAt'];
343
352
  // return Reflect.getMetadataKeys(CommonEntity.prototype) as (keyof CommonEntity)[];
@@ -1,5 +1,9 @@
1
- import { Injectable } from '@nestjs/common';
1
+ import { CACHE_MANAGER } from '@nestjs/cache-manager';
2
+ import { Inject, Injectable } from '@nestjs/common';
3
+ import { Cache } from 'cache-manager';
4
+ import { createHash } from 'crypto';
2
5
  import { ModelMetadata } from 'src';
6
+ import { shouldUseCache } from 'src/helpers/cache.helper';
3
7
  import { DataSource } from 'typeorm';
4
8
  import { SolidBaseRepository } from './solid-base.repository';
5
9
 
@@ -7,9 +11,48 @@ import { SolidBaseRepository } from './solid-base.repository';
7
11
  export class ModelMetadataRepository extends SolidBaseRepository<ModelMetadata> {
8
12
  constructor(
9
13
  readonly dataSource: DataSource,
14
+ @Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
10
15
  // readonly requestContextService: RequestContextService,
11
16
  // readonly securityRuleRepository: SecurityRuleRepository,
12
17
  ) {
13
18
  super(ModelMetadata, dataSource, null, null);
14
19
  }
15
- }
20
+
21
+ async find(options?: any): Promise<ModelMetadata[]> {
22
+ if (!shouldUseCache()) {
23
+ return super.find(options);
24
+ }
25
+
26
+ const cacheKey = this.buildCacheKey('find', options);
27
+ const cached = await this.cacheManager.get<ModelMetadata[]>(cacheKey);
28
+ if (cached !== undefined) {
29
+ return cached;
30
+ }
31
+
32
+ const result = await super.find(options);
33
+ await this.cacheManager.set(cacheKey, result);
34
+ return result;
35
+ }
36
+
37
+ async findOne(options: any): Promise<ModelMetadata | null> {
38
+ if (!shouldUseCache()) {
39
+ return super.findOne(options);
40
+ }
41
+
42
+ const cacheKey = this.buildCacheKey('findOne', options);
43
+ const cached = await this.cacheManager.get<ModelMetadata | null>(cacheKey);
44
+ if (cached !== undefined) {
45
+ return cached;
46
+ }
47
+
48
+ const result = await super.findOne(options);
49
+ await this.cacheManager.set(cacheKey, result);
50
+ return result;
51
+ }
52
+
53
+ private buildCacheKey(method: 'find' | 'findOne', options: unknown): string {
54
+ const serialized = JSON.stringify(options ?? {});
55
+ const hash = createHash('sha256').update(serialized).digest('hex');
56
+ return `modelMetadataRepo:${method}:${hash}`;
57
+ }
58
+ }
@@ -0,0 +1,6 @@
1
+ 1. Do i need to create a storeStreams method for aws service too?
2
+ - Handle later
3
+ 2. queues handling -> if queues is enabled by default, i.e triggerExport(exportTransactionEntity.id).
4
+ - startExport should either return the data or return the transaction id
5
+ 3. How to handle scenarios wherein, nested related exist.(do i need to only get the userkey)
6
+ - show the userKey