@solidxai/core 0.1.6 → 0.1.7
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.
- package/CHANGELOG.md +71 -0
- package/dist/controllers/dashboard-layout.controller.d.ts +47 -0
- package/dist/controllers/dashboard-layout.controller.d.ts.map +1 -0
- package/dist/controllers/dashboard-layout.controller.js +204 -0
- package/dist/controllers/dashboard-layout.controller.js.map +1 -0
- package/dist/controllers/scheduled-job.controller.d.ts +1 -0
- package/dist/controllers/scheduled-job.controller.d.ts.map +1 -1
- package/dist/controllers/scheduled-job.controller.js +12 -0
- package/dist/controllers/scheduled-job.controller.js.map +1 -1
- package/dist/dtos/create-dashboard-layout.dto.d.ts +8 -0
- package/dist/dtos/create-dashboard-layout.dto.d.ts.map +1 -0
- package/dist/dtos/create-dashboard-layout.dto.js +53 -0
- package/dist/dtos/create-dashboard-layout.dto.js.map +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts +1 -0
- package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -1
- package/dist/dtos/create-dashboard-variable.dto.js +7 -1
- package/dist/dtos/create-dashboard-variable.dto.js.map +1 -1
- package/dist/dtos/update-dashboard-layout.dto.d.ts +8 -0
- package/dist/dtos/update-dashboard-layout.dto.d.ts.map +1 -0
- package/dist/dtos/update-dashboard-layout.dto.js +53 -0
- package/dist/dtos/update-dashboard-layout.dto.js.map +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts +1 -0
- package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -1
- package/dist/dtos/update-dashboard-variable.dto.js +7 -1
- package/dist/dtos/update-dashboard-variable.dto.js.map +1 -1
- package/dist/entities/action-metadata.entity.d.ts.map +1 -1
- package/dist/entities/action-metadata.entity.js.map +1 -1
- package/dist/entities/ai-interaction.entity.d.ts.map +1 -1
- package/dist/entities/ai-interaction.entity.js +5 -4
- package/dist/entities/ai-interaction.entity.js.map +1 -1
- package/dist/entities/chatter-message-details.entity.d.ts +1 -0
- package/dist/entities/chatter-message-details.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message-details.entity.js +9 -4
- package/dist/entities/chatter-message-details.entity.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +4 -3
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/common.entity.js +1 -1
- package/dist/entities/common.entity.js.map +1 -1
- package/dist/entities/dashboard-layout.entity.d.ts +9 -0
- package/dist/entities/dashboard-layout.entity.d.ts.map +1 -0
- package/dist/entities/dashboard-layout.entity.js +41 -0
- package/dist/entities/dashboard-layout.entity.js.map +1 -0
- package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js +5 -4
- package/dist/entities/dashboard-question-sql-dataset-config.entity.js.map +1 -1
- package/dist/entities/dashboard-question.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-question.entity.js +5 -4
- package/dist/entities/dashboard-question.entity.js.map +1 -1
- package/dist/entities/dashboard-variable.entity.d.ts +1 -0
- package/dist/entities/dashboard-variable.entity.d.ts.map +1 -1
- package/dist/entities/dashboard-variable.entity.js +10 -4
- package/dist/entities/dashboard-variable.entity.js.map +1 -1
- package/dist/entities/dashboard.entity.d.ts +2 -0
- package/dist/entities/dashboard.entity.d.ts.map +1 -1
- package/dist/entities/dashboard.entity.js +9 -3
- package/dist/entities/dashboard.entity.js.map +1 -1
- package/dist/entities/email-attachment.entity.d.ts.map +1 -1
- package/dist/entities/email-attachment.entity.js +2 -1
- package/dist/entities/email-attachment.entity.js.map +1 -1
- package/dist/entities/email-template.entity.js +1 -1
- package/dist/entities/email-template.entity.js.map +1 -1
- package/dist/entities/export-transaction.entity.d.ts.map +1 -1
- package/dist/entities/export-transaction.entity.js +2 -1
- package/dist/entities/export-transaction.entity.js.map +1 -1
- package/dist/entities/field-metadata.entity.js +2 -2
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/entities/import-transaction-error-log.entity.d.ts.map +1 -1
- package/dist/entities/import-transaction-error-log.entity.js +3 -2
- package/dist/entities/import-transaction-error-log.entity.js.map +1 -1
- package/dist/entities/import-transaction.entity.d.ts.map +1 -1
- package/dist/entities/import-transaction.entity.js +2 -1
- package/dist/entities/import-transaction.entity.js.map +1 -1
- package/dist/entities/legacy-common.entity.d.ts.map +1 -1
- package/dist/entities/legacy-common.entity.js +1 -1
- package/dist/entities/legacy-common.entity.js.map +1 -1
- package/dist/entities/mq-message-queue.entity.d.ts.map +1 -1
- package/dist/entities/mq-message-queue.entity.js.map +1 -1
- package/dist/entities/mq-message.entity.d.ts.map +1 -1
- package/dist/entities/mq-message.entity.js +5 -3
- package/dist/entities/mq-message.entity.js.map +1 -1
- package/dist/entities/saved-filters.entity.d.ts.map +1 -1
- package/dist/entities/saved-filters.entity.js +3 -2
- package/dist/entities/saved-filters.entity.js.map +1 -1
- package/dist/entities/security-rule.entity.d.ts.map +1 -1
- package/dist/entities/security-rule.entity.js +2 -1
- package/dist/entities/security-rule.entity.js.map +1 -1
- package/dist/entities/sms-template.entity.js +1 -1
- package/dist/entities/sms-template.entity.js.map +1 -1
- package/dist/entities/user-view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/user-view-metadata.entity.js +2 -1
- package/dist/entities/user-view-metadata.entity.js.map +1 -1
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +2 -0
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entities/view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/view-metadata.entity.js.map +1 -1
- package/dist/helpers/bootstrap.helper.d.ts +14 -0
- package/dist/helpers/bootstrap.helper.d.ts.map +1 -0
- package/dist/helpers/bootstrap.helper.js +132 -0
- package/dist/helpers/bootstrap.helper.js.map +1 -0
- package/dist/helpers/cache.helper.d.ts +2 -0
- package/dist/helpers/cache.helper.d.ts.map +1 -0
- package/dist/helpers/cache.helper.js +8 -0
- package/dist/helpers/cache.helper.js.map +1 -0
- package/dist/helpers/cors.helper.d.ts.map +1 -1
- package/dist/helpers/cors.helper.js +13 -4
- package/dist/helpers/cors.helper.js.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts +2 -2
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js +8 -5
- package/dist/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.js.map +1 -1
- package/dist/helpers/solid-registry.d.ts +3 -0
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js +7 -0
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
- package/dist/helpers/typeorm-db-helper.js +21 -0
- package/dist/helpers/typeorm-db-helper.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +6 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/chatter-queue-options.js +1 -1
- package/dist/jobs/chatter-queue-options.js.map +1 -1
- package/dist/jobs/chatter-queue-publisher.service.d.ts +9 -9
- package/dist/jobs/chatter-queue-publisher.service.d.ts.map +1 -1
- package/dist/jobs/chatter-queue-publisher.service.js +5 -5
- package/dist/jobs/chatter-queue-publisher.service.js.map +1 -1
- package/dist/jobs/chatter-queue-subscriber.service.d.ts +4 -4
- package/dist/jobs/chatter-queue-subscriber.service.d.ts.map +1 -1
- package/dist/jobs/chatter-queue-subscriber.service.js +11 -11
- package/dist/jobs/chatter-queue-subscriber.service.js.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts +2 -0
- package/dist/jobs/computed-field-evaluation-queue-options.d.ts.map +1 -1
- package/dist/jobs/computed-field-evaluation-queue-options.js +2 -0
- package/dist/jobs/computed-field-evaluation-queue-options.js.map +1 -1
- package/dist/jobs/database/chatter-queue-options-database.d.ts +8 -0
- package/dist/jobs/database/chatter-queue-options-database.d.ts.map +1 -0
- package/dist/jobs/database/chatter-queue-options-database.js +10 -0
- package/dist/jobs/database/chatter-queue-options-database.js.map +1 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.d.ts +12 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.js +39 -0
- package/dist/jobs/database/chatter-queue-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.d.ts +19 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.js +62 -0
- package/dist/jobs/database/chatter-queue-subscriber-database.service.js.map +1 -0
- package/dist/repository/dashboard-layout.repository.d.ts +12 -0
- package/dist/repository/dashboard-layout.repository.d.ts.map +1 -0
- package/dist/repository/dashboard-layout.repository.js +34 -0
- package/dist/repository/dashboard-layout.repository.js.map +1 -0
- package/dist/repository/model-metadata.repository.d.ts +6 -1
- package/dist/repository/model-metadata.repository.d.ts.map +1 -1
- package/dist/repository/model-metadata.repository.js +41 -2
- package/dist/repository/model-metadata.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +4 -4
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +445 -35
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +45 -21
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +4 -4
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +59 -9
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts +7 -3
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js +61 -22
- package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js.map +1 -1
- package/dist/services/crud.service.js +1 -1
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/dashboard-layout.service.d.ts +20 -0
- package/dist/services/dashboard-layout.service.d.ts.map +1 -0
- package/dist/services/dashboard-layout.service.js +120 -0
- package/dist/services/dashboard-layout.service.js.map +1 -0
- package/dist/services/dashboard-question.service.d.ts +4 -0
- package/dist/services/dashboard-question.service.d.ts.map +1 -1
- package/dist/services/dashboard-question.service.js +22 -8
- package/dist/services/dashboard-question.service.js.map +1 -1
- package/dist/services/dashboard.service.d.ts +2 -0
- package/dist/services/dashboard.service.d.ts.map +1 -1
- package/dist/services/dashboard.service.js +4 -0
- package/dist/services/dashboard.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts +3 -1
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +122 -8
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/permission-metadata.service.d.ts +5 -1
- package/dist/services/permission-metadata.service.d.ts.map +1 -1
- package/dist/services/permission-metadata.service.js +66 -20
- package/dist/services/permission-metadata.service.js.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
- package/dist/services/question-data-providers/interfaces.d.ts +1 -0
- package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
- package/dist/services/question-data-providers/interfaces.js +1 -0
- package/dist/services/question-data-providers/interfaces.js.map +1 -0
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
- package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
- package/dist/services/queues/database-subscriber.service.d.ts +4 -2
- package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/database-subscriber.service.js +15 -2
- package/dist/services/queues/database-subscriber.service.js.map +1 -1
- package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
- package/dist/services/queues/publisher-factory.service.js +4 -7
- package/dist/services/queues/publisher-factory.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.d.ts +1 -0
- package/dist/services/queues/rabbitmq-publisher.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.js +6 -1
- package/dist/services/queues/rabbitmq-publisher.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts +9 -3
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +93 -10
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/services/request-context.service.d.ts +2 -1
- package/dist/services/request-context.service.d.ts.map +1 -1
- package/dist/services/request-context.service.js.map +1 -1
- package/dist/services/scheduled-job.service.d.ts +6 -1
- package/dist/services/scheduled-job.service.d.ts.map +1 -1
- package/dist/services/scheduled-job.service.js +26 -2
- package/dist/services/scheduled-job.service.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.interface.d.ts +2 -0
- package/dist/services/scheduled-jobs/scheduler.interface.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.interface.js.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.d.ts +6 -2
- package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.js +75 -17
- package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
- package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
- package/dist/services/solid-introspect.service.d.ts +6 -1
- package/dist/services/solid-introspect.service.d.ts.map +1 -1
- package/dist/services/solid-introspect.service.js +27 -2
- package/dist/services/solid-introspect.service.js.map +1 -1
- package/dist/services/solid-ts-morph.service.d.ts +9 -0
- package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
- package/dist/services/solid-ts-morph.service.js +76 -0
- package/dist/services/solid-ts-morph.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +16 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts +10 -7
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +58 -85
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.js +3 -1
- package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts +0 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.js +3 -13
- package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
- package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
- package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
- package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
- package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
- package/dist/winston.logger.d.ts.map +1 -1
- package/dist/winston.logger.js +2 -1
- package/dist/winston.logger.js.map +1 -1
- package/package.json +3 -1
- package/sql/default/mariadb/proc_CleanupModelMetadata.sql +153 -0
- package/sql/default/mariadb/proc_CleanupModuleMetadata.sql +56 -0
- package/sql/default/mysql/proc_CleanupModelMetadata.sql +153 -0
- package/sql/default/mysql/proc_CleanupModuleMetadata.sql +56 -0
- package/src/controllers/dashboard-layout.controller.ts +106 -0
- package/src/controllers/scheduled-job.controller.ts +6 -0
- package/src/dtos/create-dashboard-layout.dto.ts +31 -0
- package/src/dtos/create-dashboard-variable.dto.ts +4 -0
- package/src/dtos/update-dashboard-layout.dto.ts +30 -0
- package/src/dtos/update-dashboard-variable.dto.ts +5 -1
- package/src/entities/action-metadata.entity.ts +3 -2
- package/src/entities/ai-interaction.entity.ts +5 -4
- package/src/entities/chatter-message-details.entity.ts +7 -3
- package/src/entities/chatter-message.entity.ts +4 -3
- package/src/entities/common.entity.ts +2 -2
- package/src/entities/dashboard-layout.entity.ts +18 -0
- package/src/entities/dashboard-question-sql-dataset-config.entity.ts +5 -4
- package/src/entities/dashboard-question.entity.ts +5 -4
- package/src/entities/dashboard-variable.entity.ts +9 -4
- package/src/entities/dashboard.entity.ts +7 -2
- package/src/entities/email-attachment.entity.ts +2 -1
- package/src/entities/email-template.entity.ts +1 -1
- package/src/entities/export-transaction.entity.ts +2 -1
- package/src/entities/field-metadata.entity.ts +2 -2
- package/src/entities/import-transaction-error-log.entity.ts +3 -2
- package/src/entities/import-transaction.entity.ts +2 -1
- package/src/entities/legacy-common.entity.ts +3 -4
- package/src/entities/mq-message-queue.entity.ts +8 -8
- package/src/entities/mq-message.entity.ts +5 -3
- package/src/entities/saved-filters.entity.ts +3 -2
- package/src/entities/security-rule.entity.ts +2 -1
- package/src/entities/sms-template.entity.ts +1 -1
- package/src/entities/user-view-metadata.entity.ts +2 -1
- package/src/entities/user.entity.ts +37 -2
- package/src/entities/view-metadata.entity.ts +3 -0
- package/src/helpers/bootstrap.helper.ts +222 -0
- package/src/helpers/cache.helper.ts +5 -0
- package/src/helpers/cors.helper.ts +26 -6
- package/src/helpers/field-crud-managers/SelectionDynamicFieldCrudManager.ts +9 -6
- package/src/helpers/solid-registry.ts +10 -5
- package/src/helpers/typeorm-db-helper.ts +26 -0
- package/src/index.ts +3 -0
- package/src/interfaces.ts +10 -1
- package/src/jobs/chatter-queue-options.ts +1 -1
- package/src/jobs/chatter-queue-publisher.service.ts +11 -11
- package/src/jobs/chatter-queue-subscriber.service.ts +13 -8
- package/src/jobs/computed-field-evaluation-queue-options.ts +2 -0
- package/src/jobs/database/chatter-queue-options-database.ts +9 -0
- package/src/jobs/database/chatter-queue-publisher-database.service.ts +24 -0
- package/src/jobs/database/chatter-queue-subscriber-database.service.ts +53 -0
- package/src/repository/dashboard-layout.repository.ts +17 -0
- package/src/repository/model-metadata.repository.ts +45 -2
- package/src/seeders/module-metadata-seeder.service.ts +5 -5
- package/src/seeders/seed-data/solid-core-metadata.json +446 -36
- package/src/services/authentication.service.ts +47 -24
- package/src/services/chatter-message.service.ts +67 -9
- package/src/services/computed-fields/entity/sequence-num-computed-field-provider.ts +79 -40
- package/src/services/crud.service.ts +1 -1
- package/src/services/dashboard-layout.service.ts +111 -0
- package/src/services/dashboard-question.service.ts +23 -4
- package/src/services/dashboard.service.ts +7 -0
- package/src/services/model-metadata.service.ts +131 -50
- package/src/services/permission-metadata.service.ts +73 -20
- package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
- package/src/services/question-data-providers/interfaces.ts +0 -0
- package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
- package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
- package/src/services/queues/database-subscriber.service.ts +19 -2
- package/src/services/queues/publisher-factory.service.ts +9 -7
- package/src/services/queues/rabbitmq-publisher.service.ts +8 -2
- package/src/services/queues/rabbitmq-subscriber.service.ts +139 -11
- package/src/services/request-context.service.ts +2 -1
- package/src/services/scheduled-job.service.ts +31 -2
- package/src/services/scheduled-jobs/scheduler.interface.ts +4 -1
- package/src/services/scheduled-jobs/scheduler.service.ts +82 -20
- package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
- package/src/services/solid-introspect.service.ts +28 -0
- package/src/services/solid-ts-morph.service.ts +98 -0
- package/src/solid-core.module.ts +21 -2
- package/src/subscribers/audit.subscriber.ts +63 -271
- package/src/subscribers/computed-entity-field.subscriber.ts +3 -3
- package/src/subscribers/created-by-updated-by.subscriber.ts +22 -16
- package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
- package/src/winston.logger.ts +2 -1
package/src/solid-core.module.ts
CHANGED
|
@@ -94,6 +94,10 @@ import { Msg91SmsQueuePublisher } from './jobs/msg91-sms-publisher.service';
|
|
|
94
94
|
import { Msg91SmsQueueSubscriber } from './jobs/msg91-sms-subscriber.service';
|
|
95
95
|
import { SmtpEmailQueuePublisherRabbitmq } from './jobs/smtp-email-publisher.service';
|
|
96
96
|
import { SmtpEmailQueueSubscriberRabbitmq } from './jobs/smtp-email-subscriber.service';
|
|
97
|
+
import { ChatterQueuePublisherRabbitmq } from './jobs/chatter-queue-publisher.service';
|
|
98
|
+
import { ChatterQueueSubscriberRabbitmq } from './jobs/chatter-queue-subscriber.service';
|
|
99
|
+
import { ChatterQueuePublisherDatabase } from './jobs/database/chatter-queue-publisher-database.service';
|
|
100
|
+
import { ChatterQueueSubscriberDatabase } from './jobs/database/chatter-queue-subscriber-database.service';
|
|
97
101
|
import { TestQueuePublisher } from './jobs/test-queue-publisher.service';
|
|
98
102
|
import { TestQueueSubscriber } from './jobs/test-queue-subscriber.service';
|
|
99
103
|
import { UserRegistrationListener } from './listeners/user-registration.listener';
|
|
@@ -133,6 +137,8 @@ import { ChatterMessageController } from './controllers/chatter-message.controll
|
|
|
133
137
|
import { DashboardQuestionSqlDatasetConfigController } from './controllers/dashboard-question-sql-dataset-config.controller';
|
|
134
138
|
import { DashboardQuestionController } from './controllers/dashboard-question.controller';
|
|
135
139
|
import { DashboardVariableController } from './controllers/dashboard-variable.controller';
|
|
140
|
+
import { DashboardLayoutController } from './controllers/dashboard-layout.controller';
|
|
141
|
+
|
|
136
142
|
import { DashboardController } from './controllers/dashboard.controller';
|
|
137
143
|
import { ExportTemplateController } from './controllers/export-template.controller';
|
|
138
144
|
import { ExportTransactionController } from './controllers/export-transaction.controller';
|
|
@@ -156,6 +162,8 @@ import { ChatterMessage } from './entities/chatter-message.entity';
|
|
|
156
162
|
import { DashboardQuestionSqlDatasetConfig } from './entities/dashboard-question-sql-dataset-config.entity';
|
|
157
163
|
import { DashboardQuestion } from './entities/dashboard-question.entity';
|
|
158
164
|
import { DashboardVariable } from './entities/dashboard-variable.entity';
|
|
165
|
+
import { DashboardLayout } from './entities/dashboard-layout.entity';
|
|
166
|
+
|
|
159
167
|
import { Dashboard } from './entities/dashboard.entity';
|
|
160
168
|
import { ExportTemplate } from './entities/export-template.entity';
|
|
161
169
|
import { ExportTransaction } from './entities/export-transaction.entity';
|
|
@@ -221,6 +229,8 @@ import { DashboardQuestionSqlDatasetConfigRepository } from './repository/dashbo
|
|
|
221
229
|
import { DashboardQuestionRepository } from './repository/dashboard-question.repository';
|
|
222
230
|
import { DashboardVariableRepository } from './repository/dashboard-variable.repository';
|
|
223
231
|
import { DashboardRepository } from './repository/dashboard.repository';
|
|
232
|
+
import { DashboardLayoutRepository } from './repository/dashboard-layout.repository';
|
|
233
|
+
|
|
224
234
|
import { EmailTemplateRepository } from './repository/email-template.repository';
|
|
225
235
|
import { ExportTemplateRepository } from './repository/export-template.repository';
|
|
226
236
|
import { ExportTransactionRepository } from './repository/export-transaction.repository';
|
|
@@ -263,6 +273,8 @@ import { DashboardVariableSQLDynamicProvider } from './services/dashboard-select
|
|
|
263
273
|
import { DasbhoardVariableTestDynamicProvider } from './services/dashboard-selection-providers/dashboard-variable-test-dynamic-provider.service';
|
|
264
274
|
import { DashboardVariableService } from './services/dashboard-variable.service';
|
|
265
275
|
import { DashboardService } from './services/dashboard.service';
|
|
276
|
+
import { DashboardLayoutService } from './services/dashboard-layout.service';
|
|
277
|
+
|
|
266
278
|
import { ExcelService } from './services/excel.service';
|
|
267
279
|
import { ExportTemplateService } from './services/export-template.service';
|
|
268
280
|
import { ExportTransactionService } from './services/export-transaction.service';
|
|
@@ -329,6 +341,7 @@ import { ImageEncodingService } from './helpers/image-encoding.helper';
|
|
|
329
341
|
import { SolidMicroserviceAdapter } from './helpers/solid-microservice-adapter.service';
|
|
330
342
|
import { InfoCommand } from './commands/info.command';
|
|
331
343
|
import { ListOfRolesSelectionProvider } from './services/selection-providers/list-of-roles-selectionproviders.service';
|
|
344
|
+
import { Entity } from 'typeorm';
|
|
332
345
|
|
|
333
346
|
|
|
334
347
|
@Global()
|
|
@@ -343,6 +356,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
343
356
|
DashboardQuestion,
|
|
344
357
|
DashboardQuestionSqlDatasetConfig,
|
|
345
358
|
DashboardVariable,
|
|
359
|
+
DashboardLayout,
|
|
346
360
|
EmailAttachment,
|
|
347
361
|
EmailTemplate,
|
|
348
362
|
ExportTemplate,
|
|
@@ -414,6 +428,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
414
428
|
DashboardQuestionController,
|
|
415
429
|
DashboardQuestionSqlDatasetConfigController,
|
|
416
430
|
DashboardVariableController,
|
|
431
|
+
DashboardLayoutController,
|
|
417
432
|
EmailTemplateController,
|
|
418
433
|
ExportTemplateController,
|
|
419
434
|
ExportTransactionController,
|
|
@@ -584,8 +599,10 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
584
599
|
TestQueuePublisher,
|
|
585
600
|
TestQueueSubscriber,
|
|
586
601
|
|
|
587
|
-
|
|
588
|
-
|
|
602
|
+
ChatterQueuePublisherRabbitmq,
|
|
603
|
+
ChatterQueueSubscriberRabbitmq,
|
|
604
|
+
ChatterQueuePublisherDatabase,
|
|
605
|
+
ChatterQueueSubscriberDatabase,
|
|
589
606
|
|
|
590
607
|
TestQueuePublisherDatabase,
|
|
591
608
|
TestQueueSubscriberDatabase,
|
|
@@ -638,6 +655,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
638
655
|
UserActivityHistoryService,
|
|
639
656
|
DashboardService,
|
|
640
657
|
DashboardVariableService,
|
|
658
|
+
DashboardLayoutService,
|
|
641
659
|
DashboardQuestionService,
|
|
642
660
|
DashboardVariableSQLDynamicProvider,
|
|
643
661
|
DasbhoardVariableTestDynamicProvider,
|
|
@@ -682,6 +700,7 @@ import { ListOfRolesSelectionProvider } from './services/selection-providers/lis
|
|
|
682
700
|
DashboardQuestionSqlDatasetConfigRepository,
|
|
683
701
|
DashboardQuestionRepository,
|
|
684
702
|
DashboardVariableRepository,
|
|
703
|
+
DashboardLayoutRepository,
|
|
685
704
|
EmailTemplateRepository,
|
|
686
705
|
ExportTemplateRepository,
|
|
687
706
|
ExportTransactionRepository,
|
|
@@ -1,32 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
|
|
1
|
+
import { Injectable, Logger, Scope } from '@nestjs/common';
|
|
3
2
|
import { lowerFirst } from 'src/helpers/string.helper';
|
|
4
|
-
import {
|
|
3
|
+
import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
5
4
|
import { DataSource, EntityMetadata, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type DeferredCall =
|
|
10
|
-
| { kind: 'insert'; args: Parameters<ChatterMessageService['postAuditMessageOnInsert']> }
|
|
11
|
-
| { kind: 'update'; args: Parameters<ChatterMessageService['postAuditMessageOnUpdate']> }
|
|
12
|
-
| { kind: 'delete'; args: Parameters<ChatterMessageService['postAuditMessageOnDelete']> };
|
|
5
|
+
import { AuditQueuePayload } from 'src/jobs/chatter-queue-publisher.service';
|
|
6
|
+
import { RequestContextService } from 'src/services/request-context.service';
|
|
7
|
+
import { PublisherFactory } from 'src/services/queues/publisher-factory.service';
|
|
13
8
|
|
|
14
9
|
@Injectable({scope: Scope.TRANSIENT})
|
|
15
|
-
// @EventSubscriber()
|
|
16
10
|
export class AuditSubscriber implements EntitySubscriberInterface {
|
|
11
|
+
private readonly logger = new Logger(AuditSubscriber.name);
|
|
17
12
|
private dataSource: DataSource;
|
|
18
13
|
constructor(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
private readonly
|
|
22
|
-
|
|
23
|
-
// private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
24
|
-
@Inject(forwardRef(() => ModelMetadataRepository))
|
|
25
|
-
private readonly modelMetadataRepo: ModelMetadataRepository,
|
|
26
|
-
private readonly modelMetadataHelperService: ModelMetadataHelperService,
|
|
27
|
-
) {
|
|
28
|
-
// this.dataSource.subscribers.push(this);
|
|
29
|
-
}
|
|
14
|
+
private readonly publisherFactory: PublisherFactory<AuditQueuePayload>,
|
|
15
|
+
private readonly solidRegistry: SolidRegistry,
|
|
16
|
+
private readonly requestContextService: RequestContextService,
|
|
17
|
+
) { }
|
|
30
18
|
|
|
31
19
|
bindToDataSource(dataSource: DataSource) {
|
|
32
20
|
this.dataSource = dataSource;
|
|
@@ -34,90 +22,61 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
34
22
|
}
|
|
35
23
|
|
|
36
24
|
// Per-transaction buffer (auto-GC when queryRunner is gone)
|
|
37
|
-
private perTxn = new WeakMap<any,
|
|
25
|
+
private perTxn = new WeakMap<any, AuditQueuePayload[]>();
|
|
38
26
|
|
|
39
|
-
private enqueue(event: { queryRunner: any },
|
|
27
|
+
private enqueue(event: { queryRunner: any }, payload: AuditQueuePayload) {
|
|
40
28
|
const qr = event.queryRunner;
|
|
41
29
|
const arr = this.perTxn.get(qr) ?? [];
|
|
42
|
-
arr.push(
|
|
30
|
+
arr.push(payload);
|
|
43
31
|
this.perTxn.set(qr, arr);
|
|
44
32
|
}
|
|
45
33
|
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
singularName: lowerFirst(metadata.name)
|
|
50
|
-
},
|
|
51
|
-
relations: {
|
|
52
|
-
fields: true,
|
|
53
|
-
module: true
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
if (!model || !model.enableAuditTracking) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const modelFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName)
|
|
62
|
-
|
|
63
|
-
const auditFields = modelFields.filter(field =>
|
|
64
|
-
field.enableAuditTracking &&
|
|
65
|
-
!['mediaSingle', 'mediaMultiple', 'richText', 'json'].includes(field.type) &&
|
|
66
|
-
!(field.type === 'relation' && field.relationType === 'one-to-many')
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
if (auditFields.length === 0) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// if (!entity) {
|
|
74
|
-
// console.warn(`[AuditSubscriber] Skipping audit for ${metadata.name} – entity is undefined or null`);
|
|
75
|
-
// return false;
|
|
76
|
-
// }
|
|
34
|
+
private shouldTrackAudit(metadata: EntityMetadata): boolean {
|
|
35
|
+
return this.solidRegistry.isAuditableModel(lowerFirst(metadata.name));
|
|
36
|
+
}
|
|
77
37
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return fieldValue !== undefined && fieldValue !== null;
|
|
81
|
-
});
|
|
38
|
+
private activeUserId(): number | null {
|
|
39
|
+
return this.requestContextService.getActiveUser()?.sub ?? null;
|
|
82
40
|
}
|
|
83
41
|
|
|
84
42
|
async afterInsert(event: InsertEvent<any>) {
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
43
|
+
if (!this.shouldTrackAudit(event.metadata)) return;
|
|
44
|
+
this.enqueue(event, {
|
|
45
|
+
eventType: 'insert',
|
|
46
|
+
modelName: event.metadata.name,
|
|
47
|
+
entityId: event.entity?.id ?? null,
|
|
48
|
+
occurredAt: new Date().toISOString(),
|
|
49
|
+
after: event.entity ?? null,
|
|
50
|
+
userId: this.activeUserId(),
|
|
51
|
+
});
|
|
92
52
|
}
|
|
93
53
|
|
|
94
54
|
async afterUpdate(event: UpdateEvent<any>) {
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
55
|
+
if (!this.shouldTrackAudit(event.metadata)) return;
|
|
56
|
+
this.enqueue(event, {
|
|
57
|
+
eventType: 'update',
|
|
58
|
+
modelName: event.metadata.name,
|
|
59
|
+
entityId: event.entity?.id ?? null,
|
|
60
|
+
occurredAt: new Date().toISOString(),
|
|
61
|
+
after: event.entity ?? null,
|
|
62
|
+
// databaseEntity is only populated when the entity was fetched first (save() path).
|
|
63
|
+
// QueryBuilder update() leaves this undefined; postAuditMessageOnUpdate guards for it.
|
|
64
|
+
before: event.databaseEntity ?? null,
|
|
65
|
+
updatedColumnNames: (event.updatedColumns ?? []).map(c => c.propertyName),
|
|
66
|
+
userId: this.activeUserId(),
|
|
67
|
+
});
|
|
107
68
|
}
|
|
108
69
|
|
|
109
70
|
async afterRemove(event: RemoveEvent<any>) {
|
|
110
|
-
if (
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
});
|
|
120
|
-
}
|
|
71
|
+
if (!this.shouldTrackAudit(event.metadata)) return;
|
|
72
|
+
this.enqueue(event, {
|
|
73
|
+
eventType: 'delete',
|
|
74
|
+
modelName: event.metadata.name,
|
|
75
|
+
entityId: event.databaseEntity?.id ?? null,
|
|
76
|
+
occurredAt: new Date().toISOString(),
|
|
77
|
+
before: event.databaseEntity,
|
|
78
|
+
userId: this.activeUserId(),
|
|
79
|
+
});
|
|
121
80
|
}
|
|
122
81
|
|
|
123
82
|
// --------- transaction lifecycle ----------
|
|
@@ -125,191 +84,24 @@ export class AuditSubscriber implements EntitySubscriberInterface {
|
|
|
125
84
|
const batch = this.perTxn.get(event.queryRunner) ?? [];
|
|
126
85
|
this.perTxn.delete(event.queryRunner);
|
|
127
86
|
|
|
128
|
-
// Now
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
87
|
+
// Now outside the DB transaction — safe to publish to the queue.
|
|
88
|
+
// allSettled: publish in parallel; a single failure does not block the rest.
|
|
89
|
+
const results = await Promise.allSettled(
|
|
90
|
+
batch.map(payload => this.publisherFactory.publish({ payload }, 'ChatterQueuePublisher'))
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
results.forEach((result, i) => {
|
|
94
|
+
if (result.status === 'rejected') {
|
|
95
|
+
this.logger.error(
|
|
96
|
+
`Failed to publish audit event for ${batch[i].modelName}#${batch[i].entityId}`,
|
|
97
|
+
result.reason,
|
|
98
|
+
);
|
|
139
99
|
}
|
|
140
|
-
}
|
|
100
|
+
});
|
|
141
101
|
}
|
|
142
102
|
|
|
143
103
|
afterTransactionRollback(event: { queryRunner: any }) {
|
|
144
|
-
// Drop buffered
|
|
104
|
+
// Drop buffered payloads; the write never happened.
|
|
145
105
|
this.perTxn.delete(event.queryRunner);
|
|
146
106
|
}
|
|
147
107
|
}
|
|
148
|
-
|
|
149
|
-
// import { DataSource, EntityMetadata, EntitySubscriberInterface, EventSubscriber, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';
|
|
150
|
-
// import { Injectable } from '@nestjs/common';
|
|
151
|
-
// import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
|
152
|
-
// import { Repository } from 'typeorm';
|
|
153
|
-
// import { ModelMetadata } from '../entities/model-metadata.entity';
|
|
154
|
-
// import { lowerFirst } from 'src/helpers/string.helper';
|
|
155
|
-
// import { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';
|
|
156
|
-
// import { ChatterMessagePayload } from 'src/jobs/chatter-queue-publisher.service';
|
|
157
|
-
// import { RequestContextService } from 'src/services/request-context.service';
|
|
158
|
-
// import { PublisherFactory } from 'src/services/queues/publisher-factory.service';
|
|
159
|
-
|
|
160
|
-
// @EventSubscriber()
|
|
161
|
-
// @Injectable()
|
|
162
|
-
// export class AuditSubscriber implements EntitySubscriberInterface {
|
|
163
|
-
// private perTxn = new WeakMap<any, ChatterMessagePayload[]>();
|
|
164
|
-
|
|
165
|
-
// constructor(
|
|
166
|
-
// @InjectDataSource() private readonly dataSource: DataSource,
|
|
167
|
-
// @InjectRepository(ModelMetadata) private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
168
|
-
// private readonly modelMetadataHelperService: ModelMetadataHelperService,
|
|
169
|
-
// private readonly requestContext: RequestContextService,
|
|
170
|
-
// private readonly publisherFactory: PublisherFactory<any>
|
|
171
|
-
// ) {
|
|
172
|
-
// this.dataSource.subscribers.push(this);
|
|
173
|
-
// }
|
|
174
|
-
|
|
175
|
-
// // --- small cache to avoid metadata queries on every row ---
|
|
176
|
-
// private modelCache = new Map<string, { enable: boolean; fields: Array<{ name: string; enableAuditTracking: boolean; type: string; relationType?: string }>; ts: number }>();
|
|
177
|
-
// private cacheTTLms = 60_000;
|
|
178
|
-
|
|
179
|
-
// private async shouldTrackAudit(entity: any, metadata: EntityMetadata): Promise<{ enable: boolean; auditFields?: string[] }> {
|
|
180
|
-
// const key = metadata.name;
|
|
181
|
-
// const now = Date.now();
|
|
182
|
-
// const cached = this.modelCache.get(key);
|
|
183
|
-
// if (cached && (now - cached.ts) < this.cacheTTLms) {
|
|
184
|
-
// if (!cached.enable) return { enable: false };
|
|
185
|
-
// const fields = cached.fields.filter(f =>
|
|
186
|
-
// f.enableAuditTracking &&
|
|
187
|
-
// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&
|
|
188
|
-
// !(f.type === 'relation' && f.relationType === 'one-to-many')
|
|
189
|
-
// );
|
|
190
|
-
// const present = fields.map(f => f.name).filter(n => entity?.[n] !== undefined);
|
|
191
|
-
// return { enable: present.length > 0, auditFields: present };
|
|
192
|
-
// }
|
|
193
|
-
|
|
194
|
-
// const model = await this.modelMetadataRepo.findOne({
|
|
195
|
-
// where: { singularName: lowerFirst(metadata.name) },
|
|
196
|
-
// relations: { fields: true, module: true },
|
|
197
|
-
// });
|
|
198
|
-
// const enable = !!model?.enableAuditTracking;
|
|
199
|
-
// const fields = model?.fields ?? [];
|
|
200
|
-
// this.modelCache.set(key, { enable, fields, ts: now });
|
|
201
|
-
|
|
202
|
-
// if (!enable) return { enable: false };
|
|
203
|
-
// const filtered = fields.filter(f =>
|
|
204
|
-
// f.enableAuditTracking &&
|
|
205
|
-
// !['mediaSingle', 'mediaMultiple', 'computed', 'richText', 'json'].includes(f.type) &&
|
|
206
|
-
// !(f.type === 'relation' && f.relationType === 'one-to-many')
|
|
207
|
-
// );
|
|
208
|
-
// const present = filtered.map(f => f.name).filter(n => entity?.[n] !== undefined);
|
|
209
|
-
// return { enable: present.length > 0, auditFields: present };
|
|
210
|
-
// }
|
|
211
|
-
|
|
212
|
-
// private push(event: { queryRunner: any }, msg: ChatterMessagePayload) {
|
|
213
|
-
// const arr = this.perTxn.get(event.queryRunner) ?? [];
|
|
214
|
-
// arr.push(msg);
|
|
215
|
-
// this.perTxn.set(event.queryRunner, arr);
|
|
216
|
-
// }
|
|
217
|
-
|
|
218
|
-
// async afterInsert(event: InsertEvent<any>) {
|
|
219
|
-
// if (!event.entity) return;
|
|
220
|
-
// const enable = await this.shouldTrackAudit(event.entity, event.metadata);
|
|
221
|
-
// if (!enable) return;
|
|
222
|
-
|
|
223
|
-
// const payload: ChatterMessagePayload = {
|
|
224
|
-
// eventType: 'insert',
|
|
225
|
-
// model: event.metadata.name,
|
|
226
|
-
// entityId: String(event.entity.id ?? event.entity.uuid ?? ''),
|
|
227
|
-
// occurredAt: new Date().toISOString(),
|
|
228
|
-
// after: this.safeCopy(event.entity),
|
|
229
|
-
// userId: this.getUserId(),
|
|
230
|
-
// };
|
|
231
|
-
// this.push(event, payload);
|
|
232
|
-
// }
|
|
233
|
-
|
|
234
|
-
// async afterUpdate(event: UpdateEvent<any>) {
|
|
235
|
-
// // Updated entity may be null if you used raw query; fall back to databaseEntity
|
|
236
|
-
// const current = event.entity ?? {};
|
|
237
|
-
// const before = event.databaseEntity ?? {};
|
|
238
|
-
// const { enable, auditFields } = await this.shouldTrackAudit(current, event.metadata);
|
|
239
|
-
// if (!enable) return;
|
|
240
|
-
|
|
241
|
-
// const changedCols = (event.updatedColumns || []).map(c => c.propertyName);
|
|
242
|
-
// const payload: ChatterMessagePayload = {
|
|
243
|
-
// eventType: 'update',
|
|
244
|
-
// model: event.metadata.name,
|
|
245
|
-
// entityId: String((current as any).id ?? (before as any).id ?? ''),
|
|
246
|
-
// occurredAt: new Date().toISOString(),
|
|
247
|
-
// before: this.pick(before, auditFields || changedCols),
|
|
248
|
-
// after: this.pick(current, auditFields || changedCols),
|
|
249
|
-
// diff: changedCols,
|
|
250
|
-
// userId: this.getUserId(),
|
|
251
|
-
// };
|
|
252
|
-
// this.push(event, payload);
|
|
253
|
-
// }
|
|
254
|
-
|
|
255
|
-
// async afterRemove(event: RemoveEvent<any>) {
|
|
256
|
-
// const base = event.entity ?? event.databaseEntity;
|
|
257
|
-
// if (!base) return;
|
|
258
|
-
|
|
259
|
-
// const { enable } = await this.shouldTrackAudit(base, event.metadata);
|
|
260
|
-
// if (!enable) return;
|
|
261
|
-
|
|
262
|
-
// const payload: ChatterMessagePayload = {
|
|
263
|
-
// eventType: 'delete',
|
|
264
|
-
// model: event.metadata.name,
|
|
265
|
-
// entityId: String((base as any).id ?? ''),
|
|
266
|
-
// occurredAt: new Date().toISOString(),
|
|
267
|
-
// before: this.safeCopy(base),
|
|
268
|
-
// userId: this.getUserId(),
|
|
269
|
-
// };
|
|
270
|
-
// this.push(event, payload);
|
|
271
|
-
// }
|
|
272
|
-
|
|
273
|
-
// // Publish AFTER the transaction commits -> no idle-in-transaction
|
|
274
|
-
// async afterTransactionCommit(event: { queryRunner: any }) {
|
|
275
|
-
// const batch = this.perTxn.get(event.queryRunner) ?? [];
|
|
276
|
-
// this.perTxn.delete(event.queryRunner);
|
|
277
|
-
// for (const msg of batch) {
|
|
278
|
-
// try {
|
|
279
|
-
// await this.publisherFactory.publish({ payload: msg, parentEntity: msg.model, parentEntityId: msg.entityId }, 'ChatterQueuePublisher');
|
|
280
|
-
// } catch (err) {
|
|
281
|
-
// // log + optionally send to a DLQ or retry queue
|
|
282
|
-
// // do NOT throw; commit already happened
|
|
283
|
-
// // your RabbitMqPublisher likely tracks failures in MqMessage tables anyway
|
|
284
|
-
// }
|
|
285
|
-
// }
|
|
286
|
-
// }
|
|
287
|
-
|
|
288
|
-
// afterTransactionRollback(event: { queryRunner: any }) {
|
|
289
|
-
// this.perTxn.delete(event.queryRunner);
|
|
290
|
-
// }
|
|
291
|
-
|
|
292
|
-
// // --- small helpers to keep payloads JSON-safe and small ---
|
|
293
|
-
// private safeCopy(obj: any) {
|
|
294
|
-
// try {
|
|
295
|
-
// return JSON.parse(JSON.stringify(obj));
|
|
296
|
-
// } catch {
|
|
297
|
-
// return {}; // strip circular refs
|
|
298
|
-
// }
|
|
299
|
-
// }
|
|
300
|
-
|
|
301
|
-
// private pick(obj: any, keys: string[]) {
|
|
302
|
-
// const out: any = {};
|
|
303
|
-
// for (const k of keys) out[k] = obj?.[k];
|
|
304
|
-
// return this.safeCopy(out);
|
|
305
|
-
// }
|
|
306
|
-
|
|
307
|
-
// private getUserId(): string | null {
|
|
308
|
-
|
|
309
|
-
// const activeUser = this.requestContext.getActiveUser();
|
|
310
|
-
// if (activeUser?.sub)
|
|
311
|
-
// return String(activeUser.sub);
|
|
312
|
-
// }
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
// }
|
|
@@ -78,9 +78,9 @@ export class ComputedEntityFieldSubscriber implements EntitySubscriberInterface
|
|
|
78
78
|
modelName
|
|
79
79
|
);
|
|
80
80
|
//TODO: We can add a feature i.e dependsOn, where we can check if the computed field depends on other computed fields and evaluate them first
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
for (const computedField of computedFieldsTobeEvaluated) {
|
|
82
|
+
await this.evaluateComputedField(this.attachContext(computedField, eventContext), entity, currentOperation);
|
|
83
|
+
}
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
private handleComputedFieldEvaluationJob(entity: any, currentOperation: ComputedFieldTriggerOperation, modelName: string, eventContext?: TypeOrmEventContext) {
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Injectable, Scope } from "@nestjs/common";
|
|
2
2
|
import { InjectDataSource } from "@nestjs/typeorm";
|
|
3
|
-
import { User } from "src/entities/user.entity";
|
|
4
|
-
import { ActiveUserData } from "src/interfaces/active-user-data.interface";
|
|
5
3
|
import { RequestContextService } from "src/services/request-context.service";
|
|
6
|
-
import { DataSource, EntitySubscriberInterface,
|
|
4
|
+
import { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from "typeorm";
|
|
7
5
|
|
|
8
|
-
@Injectable({scope: Scope.TRANSIENT})
|
|
6
|
+
@Injectable({ scope: Scope.TRANSIENT })
|
|
9
7
|
// @EventSubscriber()
|
|
10
8
|
export class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {
|
|
11
9
|
private dataSource: DataSource;
|
|
@@ -30,7 +28,7 @@ export class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {
|
|
|
30
28
|
await this.stampUserField(event, false);
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
private async stampUserField(event: InsertEvent<any> | UpdateEvent<any>, isInsert: boolean){
|
|
31
|
+
private async stampUserField(event: InsertEvent<any> | UpdateEvent<any>, isInsert: boolean) {
|
|
34
32
|
if (!event.entity) {
|
|
35
33
|
return;
|
|
36
34
|
}
|
|
@@ -40,21 +38,29 @@ export class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {
|
|
|
40
38
|
return;
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
const loadedUser = await this.loadUser(activeUserOrUndefined as unknown as ActiveUserData);
|
|
41
|
+
// const loadedUser = await this.loadUser(activeUserOrUndefined as unknown as ActiveUserData);
|
|
42
|
+
// if (isInsert) {
|
|
43
|
+
// event.entity.createdBy = loadedUser?.id;
|
|
44
|
+
// event.entity.updatedBy = loadedUser?.id; // For insert, we set both createdBy and updatedBy to the same user
|
|
45
|
+
// }
|
|
46
|
+
// else {
|
|
47
|
+
// event.entity.updatedBy = loadedUser?.id;
|
|
48
|
+
// }
|
|
49
|
+
|
|
44
50
|
if (isInsert) {
|
|
45
|
-
event.entity.createdBy =
|
|
46
|
-
event.entity.updatedBy =
|
|
51
|
+
event.entity.createdBy = activeUserOrUndefined?.sub;
|
|
52
|
+
event.entity.updatedBy = activeUserOrUndefined?.sub; // For insert, we set both createdBy and updatedBy to the same user
|
|
47
53
|
}
|
|
48
54
|
else {
|
|
49
|
-
event.entity.updatedBy =
|
|
55
|
+
event.entity.updatedBy = activeUserOrUndefined?.sub;
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
|
|
53
|
-
private async loadUser(activeUser: ActiveUserData): Promise<User> {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
59
|
+
// private async loadUser(activeUser: ActiveUserData): Promise<User> {
|
|
60
|
+
// const userRepo = this.defaultDataSource.getRepository(User); // Assuming 'User' is the entity name for users in your application
|
|
61
|
+
// const loadedUser = await userRepo.findOne({
|
|
62
|
+
// where: { id: activeUser.sub }, // Assuming 'sub' is the user ID in the JWT token
|
|
63
|
+
// });
|
|
64
|
+
// return loadedUser;;
|
|
65
|
+
// }
|
|
60
66
|
}
|
|
@@ -20,59 +20,67 @@ function dateToUtcComponentString(d: Date): string {
|
|
|
20
20
|
const ss = pad(d.getUTCSeconds());
|
|
21
21
|
const ms = pad(d.getUTCMilliseconds(), 3);
|
|
22
22
|
|
|
23
|
-
// A
|
|
23
|
+
// A "naive" timestamp string representing the DB wall-clock components
|
|
24
24
|
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}.${ms}`;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
function getWallClockConfig(): { tz: string; wallTimeMode: boolean } {
|
|
28
|
+
return {
|
|
29
|
+
tz: process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC",
|
|
30
|
+
wallTimeMode: (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Returns a dayjs instance positioned at the wall-clock time for the given Date.
|
|
36
|
+
* - Wall-clock mode ON: dayjs in the configured timezone (components = wall-clock components)
|
|
37
|
+
* - Wall-clock mode OFF: dayjs in UTC
|
|
38
|
+
* Counterpart to serializeDate — use this to format/display a date value correctly.
|
|
39
|
+
*/
|
|
40
|
+
export function parseDate(date: Date): dayjs.Dayjs {
|
|
41
|
+
const { tz, wallTimeMode } = getWallClockConfig();
|
|
42
|
+
if (!wallTimeMode) return dayjs.utc(date);
|
|
43
|
+
return dayjs(date).tz(tz);
|
|
44
|
+
}
|
|
30
45
|
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Converts a Date to a string for storage in plain text columns (e.g. audit values).
|
|
48
|
+
* - Wall-clock mode ON: "YYYY-MM-DD HH:mm:ss.SSS" in the configured timezone (no Z suffix)
|
|
49
|
+
* - Wall-clock mode OFF: ISO 8601 UTC string with Z suffix
|
|
50
|
+
* The presence/absence of the Z suffix lets consumers distinguish the two cases.
|
|
51
|
+
*/
|
|
52
|
+
export function serializeDate(date: Date): string {
|
|
53
|
+
const { wallTimeMode } = getWallClockConfig();
|
|
54
|
+
if (!wallTimeMode) return date.toISOString();
|
|
55
|
+
return parseDate(date).format("YYYY-MM-DD HH:mm:ss.SSS");
|
|
56
|
+
}
|
|
33
57
|
|
|
34
|
-
|
|
58
|
+
export const LocalDateTimeTransformer: ValueTransformer = {
|
|
59
|
+
// DB -> Entity
|
|
60
|
+
from(value: Date | string | null | undefined): Date | null | undefined {
|
|
61
|
+
// critical... super important to return undefined here
|
|
35
62
|
if (value === undefined) return undefined;
|
|
36
63
|
if (value === null) return null;
|
|
37
64
|
|
|
38
|
-
|
|
65
|
+
const { tz, wallTimeMode } = getWallClockConfig();
|
|
66
|
+
|
|
67
|
+
if (!wallTimeMode) {
|
|
39
68
|
return dayjs(value).toDate();
|
|
40
69
|
}
|
|
41
70
|
|
|
42
71
|
const naive = value instanceof Date ? dateToUtcComponentString(value) : String(value);
|
|
43
|
-
return dayjs.tz(naive,
|
|
72
|
+
return dayjs.tz(naive, tz).utc().toDate();
|
|
44
73
|
},
|
|
45
74
|
|
|
46
|
-
// Entity
|
|
75
|
+
// Entity -> DB
|
|
47
76
|
to(value: Date | null | undefined): Date | null | undefined {
|
|
48
|
-
|
|
49
|
-
const SOLIDX_WALL_TIME_TZ = process.env.SOLIDX_WALL_TIME_TIMEZONE || process.env.SOLIDX_TIMEZONE || "UTC";
|
|
50
|
-
const SOLIDX_TIME_STORED_AS_WALL_TIME = (process.env.SOLIDX_TIME_STORED_AS_WALL_TIME || "").toLowerCase() === "true";
|
|
51
|
-
|
|
52
|
-
// critical... super important to return undefined here
|
|
77
|
+
// critical... super important to return undefined here
|
|
53
78
|
if (value === undefined) return undefined;
|
|
54
79
|
if (value === null) return null;
|
|
55
80
|
|
|
56
|
-
|
|
57
|
-
return dayjs(value).toDate();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const wallTimeStr = dayjs(value).tz(SOLIDX_WALL_TIME_TZ).format("YYYY-MM-DD HH:mm:ss.SSS");
|
|
81
|
+
const wallTimeStr = serializeDate(value);
|
|
61
82
|
return dayjs.utc(wallTimeStr).toDate();
|
|
62
83
|
},
|
|
63
84
|
|
|
64
|
-
utc: {
|
|
65
|
-
from(value: Date | string | null | undefined): Date | null | undefined {
|
|
66
|
-
if (value === undefined) return undefined;
|
|
67
|
-
if (value === null) return null;
|
|
68
|
-
return dayjs(value).toDate();
|
|
69
|
-
},
|
|
70
|
-
to(value: Date | null | undefined): Date | null | undefined {
|
|
71
|
-
if (value === undefined) return undefined;
|
|
72
|
-
if (value === null) return null;
|
|
73
|
-
return dayjs(value).toDate();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
85
|
};
|
|
77
86
|
|
|
78
|
-
export const UtcDateTimeTransformer = LocalDateTimeTransformer.utc;
|