@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
|
@@ -464,10 +464,6 @@ export class AuthenticationService {
|
|
|
464
464
|
|
|
465
465
|
private async notifyUserOnOtpInitiateRegistration(user: User, registrationValidationSource: string) {
|
|
466
466
|
const companyLogo = await this.getCompanyLogo();
|
|
467
|
-
const dummyOtp = this.getDummyOtpForUser(user);
|
|
468
|
-
|
|
469
|
-
if (dummyOtp)
|
|
470
|
-
return; // Do nothing if dummy otp is configured.
|
|
471
467
|
if (registrationValidationSource === PasswordlessLoginValidateWhatSources.EMAIL) {
|
|
472
468
|
const mailService = this.mailServiceFactory.getMailService();
|
|
473
469
|
mailService.sendEmailUsingTemplate(
|
|
@@ -594,13 +590,12 @@ export class AuthenticationService {
|
|
|
594
590
|
return true;
|
|
595
591
|
}
|
|
596
592
|
|
|
597
|
-
private async otp(
|
|
593
|
+
private async otp(): Promise<otp> {
|
|
598
594
|
const now = new Date();
|
|
599
595
|
const otpExpiry = this.settingService.getConfigValue<SolidCoreSetting>('otpExpiry');
|
|
600
|
-
const dummyOtp = this.getDummyOtpForUser(user);
|
|
601
596
|
now.setMinutes(now.getMinutes() + otpExpiry);
|
|
602
597
|
return {
|
|
603
|
-
token:
|
|
598
|
+
token: randomInt(100000, 999999).toString(),
|
|
604
599
|
expiresAt: now,
|
|
605
600
|
};
|
|
606
601
|
}
|
|
@@ -692,8 +687,11 @@ export class AuthenticationService {
|
|
|
692
687
|
|
|
693
688
|
const type = this.resolveLoginType(signInDto);
|
|
694
689
|
const user = await this.findUserForLogin(type, signInDto.identifier);
|
|
695
|
-
|
|
696
|
-
|
|
690
|
+
const dummyOtp = this.getDummyOtpForUser(user);
|
|
691
|
+
if (!dummyOtp) {
|
|
692
|
+
await this.assignLoginOtp(user, type);
|
|
693
|
+
this.notifyUserOnOtpInititateLogin(user, type);
|
|
694
|
+
}
|
|
697
695
|
return this.buildLoginOtpResponse(user, type);
|
|
698
696
|
}
|
|
699
697
|
|
|
@@ -738,15 +736,22 @@ export class AuthenticationService {
|
|
|
738
736
|
}
|
|
739
737
|
|
|
740
738
|
private async assignLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
|
|
741
|
-
const { token, expiresAt } = await this.otp(
|
|
739
|
+
const { token, expiresAt } = await this.otp();
|
|
742
740
|
if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
|
|
743
741
|
user.emailVerificationTokenOnLogin = token;
|
|
744
742
|
user.emailVerificationTokenOnLoginExpiresAt = expiresAt;
|
|
743
|
+
await this.userRepository.update(user.id, {
|
|
744
|
+
emailVerificationTokenOnLogin: token,
|
|
745
|
+
emailVerificationTokenOnLoginExpiresAt: expiresAt,
|
|
746
|
+
});
|
|
745
747
|
} else {
|
|
746
748
|
user.mobileVerificationTokenOnLogin = token;
|
|
747
749
|
user.mobileVerificationTokenOnLoginExpiresAt = expiresAt;
|
|
750
|
+
await this.userRepository.update(user.id, {
|
|
751
|
+
mobileVerificationTokenOnLogin: token,
|
|
752
|
+
mobileVerificationTokenOnLoginExpiresAt: expiresAt,
|
|
753
|
+
});
|
|
748
754
|
}
|
|
749
|
-
await this.userRepository.save(user);
|
|
750
755
|
}
|
|
751
756
|
|
|
752
757
|
private buildLoginOtpResponse(user: User, type: PasswordlessLoginValidateWhatSources) {
|
|
@@ -815,6 +820,15 @@ export class AuthenticationService {
|
|
|
815
820
|
|
|
816
821
|
const user = await this.findUserForLogin(type, identifier, { withRoles: true });
|
|
817
822
|
this.checkAccountBlocked(user);
|
|
823
|
+
const dummyOtp = this.getDummyOtpForUser(user);
|
|
824
|
+
|
|
825
|
+
if (dummyOtp) {
|
|
826
|
+
if (otp !== dummyOtp) {
|
|
827
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
828
|
+
}
|
|
829
|
+
return this.buildLoginTokenResponse(user);
|
|
830
|
+
}
|
|
831
|
+
|
|
818
832
|
try {
|
|
819
833
|
this.validateLoginOtp(user, otp, type);
|
|
820
834
|
} catch (e) {
|
|
@@ -822,13 +836,9 @@ export class AuthenticationService {
|
|
|
822
836
|
throw e;
|
|
823
837
|
}
|
|
824
838
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
this.clearLoginOtp(user, type);
|
|
829
|
-
|
|
830
|
-
user.failedLoginAttempts = 0;
|
|
831
|
-
await this.userRepository.save(user);
|
|
839
|
+
await this.clearLoginOtp(user, type);
|
|
840
|
+
await this.userActivityHistoryService.logEvent('login', user);
|
|
841
|
+
await this.resetFailedAttempts(user);
|
|
832
842
|
return this.buildLoginTokenResponse(user);
|
|
833
843
|
}
|
|
834
844
|
|
|
@@ -845,15 +855,27 @@ export class AuthenticationService {
|
|
|
845
855
|
}
|
|
846
856
|
}
|
|
847
857
|
|
|
848
|
-
private clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): void {
|
|
858
|
+
private async clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
|
|
849
859
|
if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
|
|
850
|
-
|
|
860
|
+
const verifiedAt = new Date();
|
|
861
|
+
user.emailVerifiedOnLoginAt = verifiedAt;
|
|
851
862
|
user.emailVerificationTokenOnLogin = null;
|
|
852
863
|
user.emailVerificationTokenOnLoginExpiresAt = null;
|
|
864
|
+
await this.userRepository.update(user.id, {
|
|
865
|
+
emailVerifiedOnLoginAt: verifiedAt,
|
|
866
|
+
emailVerificationTokenOnLogin: null,
|
|
867
|
+
emailVerificationTokenOnLoginExpiresAt: null,
|
|
868
|
+
});
|
|
853
869
|
} else {
|
|
854
|
-
|
|
870
|
+
const verifiedAt = new Date();
|
|
871
|
+
user.mobileVerifiedOnLoginAt = verifiedAt;
|
|
855
872
|
user.mobileVerificationTokenOnLogin = null;
|
|
856
873
|
user.mobileVerificationTokenOnLoginExpiresAt = null;
|
|
874
|
+
await this.userRepository.update(user.id, {
|
|
875
|
+
mobileVerifiedOnLoginAt: verifiedAt,
|
|
876
|
+
mobileVerificationTokenOnLogin: null,
|
|
877
|
+
mobileVerificationTokenOnLoginExpiresAt: null,
|
|
878
|
+
});
|
|
857
879
|
}
|
|
858
880
|
}
|
|
859
881
|
|
|
@@ -1296,14 +1318,15 @@ export class AuthenticationService {
|
|
|
1296
1318
|
}
|
|
1297
1319
|
|
|
1298
1320
|
private async incrementFailedAttempts(user: User): Promise<void> {
|
|
1299
|
-
user.failedLoginAttempts
|
|
1300
|
-
|
|
1321
|
+
const nextFailedAttempts = (user.failedLoginAttempts ?? 0) + 1;
|
|
1322
|
+
user.failedLoginAttempts = nextFailedAttempts;
|
|
1323
|
+
await this.userRepository.update(user.id, { failedLoginAttempts: nextFailedAttempts });
|
|
1301
1324
|
}
|
|
1302
1325
|
|
|
1303
1326
|
private async resetFailedAttempts(user: User): Promise<void> {
|
|
1304
1327
|
if (user.failedLoginAttempts === 0) return;
|
|
1305
1328
|
user.failedLoginAttempts = 0;
|
|
1306
|
-
await this.userRepository.
|
|
1329
|
+
await this.userRepository.update(user.id, { failedLoginAttempts: 0 });
|
|
1307
1330
|
}
|
|
1308
1331
|
|
|
1309
1332
|
//FIXME - Pending implementation
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LocalDateTimeTransformer, serializeDate } from 'src/transformers/typeorm/local-date-time-transformer';
|
|
1
2
|
import { forwardRef, Inject, Injectable } from '@nestjs/common';
|
|
2
3
|
import { ModuleRef } from "@nestjs/core";
|
|
3
4
|
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
@@ -89,13 +90,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
89
90
|
return savedMessage;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
async postAuditMessageOnInsert(entity: any,
|
|
93
|
+
async postAuditMessageOnInsert(entity: any, modelName: string, messageQueue: boolean = false) {
|
|
93
94
|
if (!entity) {
|
|
94
95
|
return;
|
|
95
96
|
}
|
|
96
97
|
const model = await this.modelMetadataRepo.findOne({
|
|
97
98
|
where: {
|
|
98
|
-
singularName: lowerFirst(
|
|
99
|
+
singularName: lowerFirst(modelName)
|
|
99
100
|
},
|
|
100
101
|
relations: {
|
|
101
102
|
fields: true,
|
|
@@ -141,6 +142,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
141
142
|
messageDetail.chatterMessage = savedMessage;
|
|
142
143
|
messageDetail.fieldName = field.name;
|
|
143
144
|
messageDetail.fieldDisplayName = field.displayName;
|
|
145
|
+
messageDetail.fieldType = field.type;
|
|
144
146
|
messageDetail.oldValue = null;
|
|
145
147
|
messageDetail.oldValueDisplay = null;
|
|
146
148
|
messageDetail.newValue = this.formatFieldValue(field, fieldValue);
|
|
@@ -150,13 +152,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
async postAuditMessageOnUpdate(entity: any,
|
|
155
|
+
async postAuditMessageOnUpdate(entity: any, modelName: string, databaseEntity: any, updatedColumns: any[] = [], messageQueue: boolean = false) {
|
|
154
156
|
if (!databaseEntity || !entity) {
|
|
155
157
|
return;
|
|
156
158
|
}
|
|
157
159
|
const model = await this.modelMetadataRepo.findOne({
|
|
158
160
|
where: {
|
|
159
|
-
singularName: lowerFirst(
|
|
161
|
+
singularName: lowerFirst(modelName)
|
|
160
162
|
},
|
|
161
163
|
relations: {
|
|
162
164
|
fields: true,
|
|
@@ -202,6 +204,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
202
204
|
|
|
203
205
|
const changedRelationFields = [];
|
|
204
206
|
if (potentialRelationFields.length > 0) {
|
|
207
|
+
const metadata = this.entityManager.connection.entityMetadatas.find(m => m.name === modelName);
|
|
205
208
|
const populatedOldEntity = await this.populateRelationFields(databaseEntity, potentialRelationFields, metadata);
|
|
206
209
|
|
|
207
210
|
for (const field of potentialRelationFields) {
|
|
@@ -257,6 +260,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
257
260
|
messageDetail.chatterMessage = savedMessage;
|
|
258
261
|
messageDetail.fieldName = field.name;
|
|
259
262
|
messageDetail.fieldDisplayName = field.displayName;
|
|
263
|
+
messageDetail.fieldType = field.type;
|
|
260
264
|
messageDetail.oldValue = this.formatFieldValue(field, oldValue);
|
|
261
265
|
messageDetail.newValue = this.formatFieldValue(field, newValue);
|
|
262
266
|
messageDetail.oldValueDisplay = await this.formatFieldValueDisplay(field, oldValue);
|
|
@@ -265,13 +269,12 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
265
269
|
}
|
|
266
270
|
}
|
|
267
271
|
|
|
268
|
-
async postAuditMessageOnDelete(
|
|
272
|
+
async postAuditMessageOnDelete(modelName: string, databaseEntity: any, messageQueue: boolean = false) {
|
|
269
273
|
const model = await this.modelMetadataRepo.findOne({
|
|
270
274
|
where: {
|
|
271
|
-
singularName: lowerFirst(
|
|
275
|
+
singularName: lowerFirst(modelName)
|
|
272
276
|
},
|
|
273
277
|
relations: {
|
|
274
|
-
fields: true,
|
|
275
278
|
module: true,
|
|
276
279
|
userKeyField: true
|
|
277
280
|
}
|
|
@@ -281,13 +284,29 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
281
284
|
return;
|
|
282
285
|
}
|
|
283
286
|
|
|
287
|
+
const modelFields = await this.modelMetadataHelperService.loadFieldHierarchy(model.singularName);
|
|
288
|
+
|
|
289
|
+
const auditFields = modelFields.filter(field =>
|
|
290
|
+
field.enableAuditTracking &&
|
|
291
|
+
!['mediaSingle', 'mediaMultiple', 'richText', 'json'].includes(field.type) &&
|
|
292
|
+
!(field.type === 'relation' && field.relationType === 'one-to-many')
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
// Populate relation fields so display values (e.g. names) are resolvable.
|
|
296
|
+
// The related entities themselves still exist in the DB after a delete.
|
|
297
|
+
const relationFields = auditFields.filter(field => field.type === 'relation');
|
|
298
|
+
const entityMetadata = this.entityManager.connection.entityMetadatas.find(m => m.name === modelName);
|
|
299
|
+
const populatedEntity = relationFields.length > 0 && entityMetadata
|
|
300
|
+
? await this.populateRelationFields(databaseEntity, relationFields, entityMetadata)
|
|
301
|
+
: { ...databaseEntity };
|
|
302
|
+
|
|
284
303
|
const chatterMessage = new ChatterMessage();
|
|
285
304
|
chatterMessage.messageType = CHATTER_MESSAGE_TYPE.AUDIT;
|
|
286
305
|
chatterMessage.messageSubType = CHATTER_MESSAGE_SUBTYPE.AUDIT_DELETE;
|
|
287
306
|
chatterMessage.coModelEntityId = databaseEntity?.id;
|
|
288
307
|
chatterMessage.coModelName = model?.singularName;
|
|
289
308
|
chatterMessage.modelDisplayName = model?.displayName;
|
|
290
|
-
chatterMessage.modelUserKey =
|
|
309
|
+
chatterMessage.modelUserKey = databaseEntity[model?.userKeyField?.name];
|
|
291
310
|
chatterMessage.messageBody = `${model?.displayName} deleted`;
|
|
292
311
|
|
|
293
312
|
const activeUser = this.requestContextService.getActiveUser();
|
|
@@ -299,7 +318,23 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
299
318
|
chatterMessage.user = null;
|
|
300
319
|
}
|
|
301
320
|
|
|
302
|
-
await this.repo.save(chatterMessage);
|
|
321
|
+
const savedMessage = await this.repo.save(chatterMessage);
|
|
322
|
+
|
|
323
|
+
for (const field of auditFields) {
|
|
324
|
+
const fieldValue = populatedEntity[field.name];
|
|
325
|
+
if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {
|
|
326
|
+
const messageDetail = new ChatterMessageDetails();
|
|
327
|
+
messageDetail.chatterMessage = savedMessage;
|
|
328
|
+
messageDetail.fieldName = field.name;
|
|
329
|
+
messageDetail.fieldDisplayName = field.displayName;
|
|
330
|
+
messageDetail.fieldType = field.type;
|
|
331
|
+
messageDetail.oldValue = this.formatFieldValue(field, fieldValue);
|
|
332
|
+
messageDetail.oldValueDisplay = await this.formatFieldValueDisplay(field, fieldValue);
|
|
333
|
+
messageDetail.newValue = null;
|
|
334
|
+
messageDetail.newValueDisplay = null;
|
|
335
|
+
await this.chatterMessageDetailsRepo.save(messageDetail);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
303
338
|
}
|
|
304
339
|
|
|
305
340
|
private formatFieldValue(field: any, value: any): string {
|
|
@@ -320,6 +355,9 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
320
355
|
}
|
|
321
356
|
}
|
|
322
357
|
|
|
358
|
+
if (value instanceof Date) {
|
|
359
|
+
return serializeDate(value);
|
|
360
|
+
}
|
|
323
361
|
|
|
324
362
|
return value.toString();
|
|
325
363
|
}
|
|
@@ -333,6 +371,10 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
333
371
|
return `${value}`;
|
|
334
372
|
}
|
|
335
373
|
|
|
374
|
+
if (['date', 'datetime', 'time'].includes(field.type)) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
|
|
336
378
|
if (field.type === 'relation') {
|
|
337
379
|
if (field.relationType === "many-to-one") {
|
|
338
380
|
if (value.name) {
|
|
@@ -618,6 +660,22 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
618
660
|
const [entities, count] = await qb.getManyAndCount();
|
|
619
661
|
this.logHeapUsed('getChatterMessages-entitiesLoaded');
|
|
620
662
|
|
|
663
|
+
// Convert date strings in message details to ISO format for consistent handling on the frontend
|
|
664
|
+
const DATE_FIELD_TYPES = ['date', 'datetime', 'time'];
|
|
665
|
+
for (const entity of entities) {
|
|
666
|
+
for (const detail of entity.chatterMessageDetails ?? []) {
|
|
667
|
+
if (!detail.fieldType || !DATE_FIELD_TYPES.includes(detail.fieldType)) continue;
|
|
668
|
+
if (detail.oldValue) {
|
|
669
|
+
const d = LocalDateTimeTransformer.from(detail.oldValue);
|
|
670
|
+
if (d) detail.oldValue = d.toISOString();
|
|
671
|
+
}
|
|
672
|
+
if (detail.newValue) {
|
|
673
|
+
const d = LocalDateTimeTransformer.from(detail.newValue);
|
|
674
|
+
if (d) detail.newValue = d.toISOString();
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
621
679
|
if (populateMedia && populateMedia.length > 0) {
|
|
622
680
|
const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);
|
|
623
681
|
this.logHeapUsed('getChatterMessages-beforePopulateMedia');
|
|
@@ -1,20 +1,28 @@
|
|
|
1
|
+
import { classify } from "@angular-devkit/core/src/utils/strings";
|
|
1
2
|
import { Injectable } from "@nestjs/common";
|
|
2
3
|
import { InjectDataSource } from "@nestjs/typeorm";
|
|
4
|
+
import { ComputedFieldTriggerOperation } from "src/dtos/create-field-metadata.dto";
|
|
3
5
|
import { ComputedFieldProvider } from "src/decorators/computed-field-provider.decorator";
|
|
4
6
|
import { CommonEntity } from "src/entities/common.entity";
|
|
5
7
|
import { ModelSequence } from "src/entities/model-sequence.entity";
|
|
6
8
|
import { ComputedFieldMetadata } from "src/helpers/solid-registry";
|
|
7
|
-
import {
|
|
8
|
-
import { DataSource,
|
|
9
|
+
import { IEntityPostComputeFieldProvider } from "src/interfaces";
|
|
10
|
+
import { DataSource, EntityManager } from "typeorm";
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
export interface SequenceNumComputedFieldContext {
|
|
12
|
-
sequenceName: string;
|
|
14
|
+
sequenceName: string;
|
|
15
|
+
/**
|
|
16
|
+
* - `'counter'` (default): increments the sequence's `currentValue` and uses it as the number.
|
|
17
|
+
* - `'entityId'`: uses the entity's own `id` as the number; does not update the counter.
|
|
18
|
+
* Only valid on `afterInsert` events.
|
|
19
|
+
*/
|
|
20
|
+
mode?: 'counter' | 'entityId';
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
@ComputedFieldProvider()
|
|
16
24
|
@Injectable()
|
|
17
|
-
export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
|
|
25
|
+
export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements IEntityPostComputeFieldProvider<T, SequenceNumComputedFieldContext> {
|
|
18
26
|
constructor(
|
|
19
27
|
@InjectDataSource()
|
|
20
28
|
private readonly dataSource: DataSource
|
|
@@ -25,23 +33,21 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
|
|
|
25
33
|
}
|
|
26
34
|
|
|
27
35
|
help(): string {
|
|
28
|
-
return "Computed field provider used to create fields whose value is based on some prefix, padding & sequence number."
|
|
36
|
+
return "Computed field provider used to create fields whose value is based on some prefix, padding & sequence number. " +
|
|
37
|
+
"Use mode='counter' (default) to auto-increment the sequence's currentValue. " +
|
|
38
|
+
"Use mode='entityId' to use the entity's own id as the number (afterInsert only, does not update the counter).";
|
|
29
39
|
}
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
41
|
+
private buildSequenceString(modelSequence: ModelSequence, numericValue: number): string {
|
|
42
|
+
const prefix = modelSequence.prefix ?? "";
|
|
43
|
+
const separator = modelSequence.separator ?? "";
|
|
44
|
+
const padded = String(numericValue).padStart(modelSequence.padding ?? 5, "0");
|
|
45
|
+
return `${prefix}${separator}${padded}`;
|
|
46
|
+
}
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*/
|
|
43
|
-
// 1️⃣ Fetch sequence row
|
|
44
|
-
const modelSequenceRepo = manager.getRepository(ModelSequence)
|
|
48
|
+
private async generateCounterSequenceValue(sequenceName: string, manager?: EntityManager): Promise<{ sequenceString: string; currentValue: number; modelSingularName: string }> {
|
|
49
|
+
const run = async (mgr: EntityManager) => {
|
|
50
|
+
const modelSequenceRepo = mgr.getRepository(ModelSequence);
|
|
45
51
|
const modelSequence = await modelSequenceRepo.findOne({
|
|
46
52
|
where: { sequenceName },
|
|
47
53
|
lock: { mode: "pessimistic_write" }
|
|
@@ -51,36 +57,69 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
|
|
|
51
57
|
throw new Error(`ModelSequence not found for ${sequenceName}`);
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
// 2️⃣ Generate next sequence value
|
|
55
60
|
const nextValue = modelSequence.currentValue + 1;
|
|
61
|
+
const sequenceString = this.buildSequenceString(modelSequence, nextValue);
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
modelSequence.currentValue = nextValue;
|
|
64
|
+
await modelSequenceRepo.save(modelSequence);
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
const
|
|
66
|
+
// Load model relation in a separate query to avoid FOR UPDATE on joined relation.
|
|
67
|
+
const modelSequenceWithModel = await modelSequenceRepo.findOne({
|
|
68
|
+
where: { id: modelSequence.id },
|
|
69
|
+
relations: { model: true },
|
|
70
|
+
});
|
|
71
|
+
const modelSingularName = modelSequenceWithModel?.model?.singularName;
|
|
72
|
+
if (!modelSingularName) {
|
|
73
|
+
throw new Error(`Model singularName not found for sequence ${sequenceName}`);
|
|
74
|
+
}
|
|
61
75
|
|
|
62
|
-
|
|
76
|
+
return { sequenceString, currentValue: nextValue, modelSingularName };
|
|
77
|
+
};
|
|
63
78
|
|
|
64
|
-
|
|
65
|
-
|
|
79
|
+
return manager ? run(manager) : this.dataSource.transaction(run);
|
|
80
|
+
}
|
|
66
81
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
82
|
+
private async generateEntityIdSequenceValue(sequenceName: string, entityId: number): Promise<{ sequenceString: string; modelSingularName: string }> {
|
|
83
|
+
const modelSequenceRepo = this.dataSource.manager.getRepository(ModelSequence);
|
|
84
|
+
const modelSequence = await modelSequenceRepo.findOne({
|
|
85
|
+
where: { sequenceName },
|
|
86
|
+
relations: { model: true },
|
|
87
|
+
});
|
|
72
88
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
if (!modelSequence) {
|
|
90
|
+
throw new Error(`ModelSequence not found for ${sequenceName}`);
|
|
91
|
+
}
|
|
76
92
|
|
|
77
|
-
|
|
78
|
-
|
|
93
|
+
const modelSingularName = modelSequence.model?.singularName;
|
|
94
|
+
if (!modelSingularName) {
|
|
95
|
+
throw new Error(`Model singularName not found for sequence ${sequenceName}`);
|
|
96
|
+
}
|
|
79
97
|
|
|
80
|
-
|
|
81
|
-
modelSequence.currentValue = nextValue;
|
|
82
|
-
await modelSequenceRepo.save(modelSequence);
|
|
83
|
-
});
|
|
98
|
+
return { sequenceString: this.buildSequenceString(modelSequence, entityId), modelSingularName };
|
|
84
99
|
}
|
|
85
100
|
|
|
86
|
-
|
|
101
|
+
async postComputeAndSaveValue(triggerEntity: T, computedFieldMetadata: ComputedFieldMetadata<SequenceNumComputedFieldContext>): Promise<void> {
|
|
102
|
+
const { sequenceName, mode = 'counter' } = computedFieldMetadata.computedFieldValueProviderCtxt ?? {};
|
|
103
|
+
|
|
104
|
+
if (!sequenceName) {
|
|
105
|
+
throw new Error("sequenceName is required for sequence computation");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let sequenceString: string;
|
|
109
|
+
let modelSingularName: string;
|
|
110
|
+
|
|
111
|
+
if (mode === 'entityId') {
|
|
112
|
+
const eventType = computedFieldMetadata.eventContext?.eventType;
|
|
113
|
+
if (eventType !== ComputedFieldTriggerOperation.afterInsert) {
|
|
114
|
+
throw new Error(`SequenceNumComputedFieldProvider with mode='entityId' only supports "${ComputedFieldTriggerOperation.afterInsert}" events, but received "${eventType}"`);
|
|
115
|
+
}
|
|
116
|
+
({ sequenceString, modelSingularName } = await this.generateEntityIdSequenceValue(sequenceName, triggerEntity.id));
|
|
117
|
+
} else {
|
|
118
|
+
({ sequenceString, modelSingularName } = await this.generateCounterSequenceValue(sequenceName));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const entityName = classify(modelSingularName);
|
|
122
|
+
const entityRepo = this.dataSource.manager.getRepository(entityName);
|
|
123
|
+
await entityRepo.update(triggerEntity.id, { [computedFieldMetadata.fieldName]: sequenceString });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -432,7 +432,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
432
432
|
// dataSource: string; // The name of the selection provider
|
|
433
433
|
// filterSchema : json // This is a custom json object that every data source will handle accordingly. We could validate the query against the selection provider
|
|
434
434
|
// values : string[]; // The values returned by the selection provider
|
|
435
|
-
const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: fieldMetadata.selectionDynamicProviderCtxt, selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };
|
|
435
|
+
const options = { ...commonOptions, selectionDynamicProvider: fieldMetadata.selectionDynamicProvider, selectionDynamicProviderCtxt: JSON.parse(fieldMetadata.selectionDynamicProviderCtxt), selectionValueType: fieldMetadata.selectionValueType as SelectionValueType, discoveryService: this.discoveryService, isMultiSelect: fieldMetadata.isMultiSelect };
|
|
436
436
|
return new SelectionDynamicFieldCrudManager(options);
|
|
437
437
|
}
|
|
438
438
|
case SolidFieldType.uuid: {
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { ModuleRef } from "@nestjs/core";
|
|
3
|
+
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
4
|
+
import { EntityManager } from 'typeorm';
|
|
5
|
+
|
|
6
|
+
import { CRUDService } from 'src/services/crud.service';
|
|
7
|
+
import { DashboardLayout } from 'src/entities/dashboard-layout.entity';
|
|
8
|
+
import { DashboardLayoutRepository } from 'src/repository/dashboard-layout.repository';
|
|
9
|
+
import { CreateDashboardLayoutDto } from 'src/dtos/create-dashboard-layout.dto';
|
|
10
|
+
import { RequestContextService } from './request-context.service';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@Injectable()
|
|
14
|
+
export class DashboardLayoutService extends CRUDService<DashboardLayout> {
|
|
15
|
+
private readonly logger = new Logger(this.constructor.name);
|
|
16
|
+
constructor(
|
|
17
|
+
@InjectEntityManager()
|
|
18
|
+
readonly entityManager: EntityManager,
|
|
19
|
+
readonly repo: DashboardLayoutRepository,
|
|
20
|
+
readonly requestContextService: RequestContextService,
|
|
21
|
+
readonly moduleRef: ModuleRef,
|
|
22
|
+
) {
|
|
23
|
+
super(entityManager, repo, 'dashboardLayout', 'solid-core', moduleRef);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async upsertUserDashboardLayout(createDtos: CreateDashboardLayoutDto) {
|
|
27
|
+
const activeUser = this.requestContextService.getActiveUser();
|
|
28
|
+
|
|
29
|
+
if (!activeUser) {
|
|
30
|
+
throw new Error('User not found');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let userId = null;
|
|
34
|
+
if (activeUser.roles.includes('Admin')) {
|
|
35
|
+
userId = null;
|
|
36
|
+
} else {
|
|
37
|
+
userId = activeUser?.sub;
|
|
38
|
+
}
|
|
39
|
+
const existingLayout = await this.repo.findOne({
|
|
40
|
+
where: {
|
|
41
|
+
user: { id: userId },
|
|
42
|
+
dashboard: {
|
|
43
|
+
id: createDtos.dashboardId
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
relations: {
|
|
47
|
+
user: true,
|
|
48
|
+
dashboard: true,
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (existingLayout) {
|
|
53
|
+
return super.update(existingLayout.id, { layout: createDtos.layout }, [], true);
|
|
54
|
+
} else {
|
|
55
|
+
const createDto = {
|
|
56
|
+
layout: createDtos.layout,
|
|
57
|
+
dashboardId: createDtos.dashboardId,
|
|
58
|
+
uesrId: userId
|
|
59
|
+
}
|
|
60
|
+
return super.create(createDto, []);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async getUserDashboardLayoutByDashboardId(dashboardId: any) {
|
|
65
|
+
const activeUser = this.requestContextService.getActiveUser();
|
|
66
|
+
|
|
67
|
+
if (!activeUser) {
|
|
68
|
+
throw new Error('User not found');
|
|
69
|
+
}
|
|
70
|
+
const userId = activeUser?.sub;
|
|
71
|
+
const existingUserLayout = await this.repo.findOne({
|
|
72
|
+
where: {
|
|
73
|
+
user: { id: userId },
|
|
74
|
+
dashboard: {
|
|
75
|
+
id: dashboardId
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
relations: {
|
|
79
|
+
user: true,
|
|
80
|
+
dashboard: true,
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (existingUserLayout) {
|
|
84
|
+
// if dahsboard for userid exists
|
|
85
|
+
return existingUserLayout;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// if not then check for default dashboard
|
|
89
|
+
const defaultLayout = await this.repo.findOne({
|
|
90
|
+
where: {
|
|
91
|
+
user: { id: null },
|
|
92
|
+
dashboard: {
|
|
93
|
+
id: dashboardId
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
relations: {
|
|
97
|
+
user: true,
|
|
98
|
+
dashboard: true,
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
if (defaultLayout) {
|
|
102
|
+
// if default layout exists return it
|
|
103
|
+
return defaultLayout;
|
|
104
|
+
} else {
|
|
105
|
+
// if default layout does not exist return empty layout
|
|
106
|
+
return {
|
|
107
|
+
layout: null
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -11,15 +11,18 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
|
11
11
|
import { DashboardQuestion } from '../entities/dashboard-question.entity';
|
|
12
12
|
import { SqlExpression, SqlExpressionOperator } from './question-data-providers/chartjs-sql-data-provider.service';
|
|
13
13
|
import { DashboardQuestionRepository } from 'src/repository/dashboard-question.repository';
|
|
14
|
+
import { QuestionSqlDataProviderContext } from 'src';
|
|
14
15
|
|
|
15
16
|
enum SOURCE_TYPE {
|
|
16
17
|
SQL = 'sql',
|
|
17
18
|
PROVIDER = 'provider',
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
|
|
21
|
-
const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
|
|
22
|
-
const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
|
|
21
|
+
export const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
|
|
22
|
+
export const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
|
|
23
|
+
export const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
|
|
24
|
+
|
|
25
|
+
export const INBUILT_SQL_DATA_PROVIDERS = [CHARTJS_SQL_DATA_PROVIDER_NAME, PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME, PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME];
|
|
23
26
|
|
|
24
27
|
@Injectable()
|
|
25
28
|
export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
|
|
@@ -50,22 +53,38 @@ export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
|
|
|
50
53
|
|
|
51
54
|
// Try to resolve the dataProvider based on a combination of sourceType and visualisedAs
|
|
52
55
|
let dataProvider = null;
|
|
56
|
+
let context = {};
|
|
53
57
|
|
|
58
|
+
// Decide which data provider to use based on the question visualisation type if sourceType is SQL.
|
|
54
59
|
if (question.sourceType === SOURCE_TYPE.SQL && ['bar', 'pie', 'line', 'donut'].includes(question.visualisedAs)) {
|
|
55
60
|
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(CHARTJS_SQL_DATA_PROVIDER_NAME);
|
|
61
|
+
context = {
|
|
62
|
+
expressions,
|
|
63
|
+
} as QuestionSqlDataProviderContext;
|
|
56
64
|
}
|
|
57
65
|
if (question.sourceType === SOURCE_TYPE.SQL && ['prime-meter-group'].includes(question.visualisedAs)) {
|
|
58
66
|
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME);
|
|
67
|
+
context = {
|
|
68
|
+
expressions,
|
|
69
|
+
} as QuestionSqlDataProviderContext;
|
|
59
70
|
}
|
|
60
71
|
if (question.sourceType === SOURCE_TYPE.SQL && ['prime-datatable'].includes(question.visualisedAs)) {
|
|
61
72
|
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME);
|
|
73
|
+
context = {
|
|
74
|
+
expressions,
|
|
75
|
+
} as QuestionSqlDataProviderContext;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// If a custom provider is specified, use that one instead
|
|
79
|
+
if (question.sourceType === SOURCE_TYPE.PROVIDER) {
|
|
80
|
+
dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(question.providerName);
|
|
62
81
|
}
|
|
63
82
|
|
|
64
83
|
if (!dataProvider) {
|
|
65
84
|
throw new NotImplementedException(`Invalid data source type ${question.sourceType}`);
|
|
66
85
|
}
|
|
67
86
|
|
|
68
|
-
return await dataProvider.getData(question,
|
|
87
|
+
return await dataProvider.getData(question, context);
|
|
69
88
|
|
|
70
89
|
}
|
|
71
90
|
|