@solidxai/core 0.1.6-beta.9 → 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/.claude/settings.local.json +15 -0
- 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/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.map +1 -1
- package/dist/entities/chatter-message-details.entity.js +4 -3
- 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/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/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/MediaFieldCrudManager.d.ts +1 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +8 -9
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.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 +2 -0
- 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 +372 -32
- 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 +33 -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.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 +21 -2
- 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/queues/database-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/database-subscriber.service.js +6 -1
- package/dist/services/queues/database-subscriber.service.js.map +1 -1
- package/dist/services/queues/publisher-factory.service.js +0 -1
- 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 +5 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +84 -9
- 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-jobs/scheduler.service.d.ts.map +1 -1
- package/dist/services/scheduled-jobs/scheduler.service.js +20 -2
- package/dist/services/scheduled-jobs/scheduler.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/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/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 +4 -3
- package/src/entities/chatter-message.entity.ts +4 -3
- 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/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/MediaFieldCrudManager.ts +9 -9
- 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 +3 -0
- 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 +373 -33
- package/src/services/1.js +6 -0
- package/src/services/chatter-message.service.ts +41 -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.service.ts +7 -0
- package/src/services/model-metadata.service.ts +22 -43
- package/src/services/permission-metadata.service.ts +73 -20
- package/src/services/queues/database-subscriber.service.ts +7 -1
- package/src/services/queues/publisher-factory.service.ts +1 -1
- package/src/services/queues/rabbitmq-publisher.service.ts +8 -2
- package/src/services/queues/rabbitmq-subscriber.service.ts +127 -10
- package/src/services/request-context.service.ts +2 -1
- package/src/services/scheduled-jobs/scheduler.service.ts +22 -4
- 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/winston.logger.ts +2 -1
- package/dist-tests/api/authenticate.spec.js +0 -119
- package/dist-tests/api/authenticate.spec.js.map +0 -1
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +0 -97
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +0 -1
- package/dist-tests/api/ping.spec.js +0 -21
- package/dist-tests/api/ping.spec.js.map +0 -1
- package/dist-tests/helpers/auth.js +0 -41
- package/dist-tests/helpers/auth.js.map +0 -1
- package/dist-tests/helpers/env.js +0 -11
- package/dist-tests/helpers/env.js.map +0 -1
|
@@ -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
|
+
}
|
|
@@ -15,6 +15,7 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
|
15
15
|
import { DashboardMapper } from 'src/mappers/dashboard-mapper';
|
|
16
16
|
import { DashboardRepository } from 'src/repository/dashboard.repository';
|
|
17
17
|
import { Dashboard } from '../entities/dashboard.entity';
|
|
18
|
+
import { CreateDashboardDto } from 'src/dtos/create-dashboard.dto';
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
export const SQL_DYNAMIC_PROVIDER_NAME = 'DashboardVariableSQLDynamicProvider';
|
|
@@ -33,6 +34,12 @@ export class DashboardService extends CRUDService<Dashboard> {
|
|
|
33
34
|
super(entityManager, repo, 'dashboard', 'solid-core', moduleRef);
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
|
|
38
|
+
async create(createDto: CreateDashboardDto, files: Express.Multer.File[]) {
|
|
39
|
+
createDto.name = createDto.name.trim().replace(/\s+/g, '-').toLowerCase();
|
|
40
|
+
return super.create(createDto, files);
|
|
41
|
+
}
|
|
42
|
+
|
|
36
43
|
async getSelectionDynamicValues(query: DashboardVariableSelectionDynamicQueryDto) {
|
|
37
44
|
// Get the dashboard variable repo
|
|
38
45
|
const dashboardVariable = await this.loadDashboardVariable(query.variableId);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BadRequestException, forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
|
2
2
|
import { InjectDataSource } from '@nestjs/typeorm';
|
|
3
3
|
import * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await
|
|
4
|
+
import * as path from 'path';
|
|
4
5
|
import { DataSource, EntityManager, In, Repository, SelectQueryBuilder } from 'typeorm';
|
|
5
6
|
import { CreateModelMetadataDto } from '../dtos/create-model-metadata.dto';
|
|
6
7
|
import { ModelMetadata } from '../entities/model-metadata.entity';
|
|
@@ -33,6 +34,7 @@ import { RoleMetadataService } from './role-metadata.service';
|
|
|
33
34
|
import { NavigationDto } from 'src/dtos/navigation.dto';
|
|
34
35
|
import { SolidIntrospectService } from './solid-introspect.service';
|
|
35
36
|
import { CRUDService } from './crud.service';
|
|
37
|
+
import { SolidTsMorphService } from './solid-ts-morph.service';
|
|
36
38
|
|
|
37
39
|
@Injectable()
|
|
38
40
|
export class ModelMetadataService {
|
|
@@ -54,8 +56,9 @@ export class ModelMetadataService {
|
|
|
54
56
|
private readonly roleService: RoleMetadataService,
|
|
55
57
|
private readonly moduleMetadataHelperService: ModuleMetadataHelperService,
|
|
56
58
|
readonly introspectService: SolidIntrospectService,
|
|
59
|
+
private readonly solidTsMorphService: SolidTsMorphService,
|
|
57
60
|
|
|
58
|
-
// No longer used.
|
|
61
|
+
// No longer used.
|
|
59
62
|
// private readonly generateCodePublihser: GenerateCodePublisherDatabase,
|
|
60
63
|
) { }
|
|
61
64
|
|
|
@@ -707,48 +710,24 @@ export class ModelMetadataService {
|
|
|
707
710
|
await fs.writeFile(filePath, updatedContent);
|
|
708
711
|
}
|
|
709
712
|
|
|
710
|
-
// <moduleName>.module.ts | Remove all references and imports of the
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
// const objectLiteral = moduleDecorator?.getCallExpression()?.getArguments()?.[0];
|
|
729
|
-
|
|
730
|
-
// if (objectLiteral && objectLiteral.getKind() === SyntaxKind.ObjectLiteralExpression) {
|
|
731
|
-
// const objectLiteralExpr = objectLiteral.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);
|
|
732
|
-
|
|
733
|
-
// for (const propName of ['imports', 'providers', 'controllers', 'exports']) {
|
|
734
|
-
// const prop = objectLiteralExpr.getProperty(propName);
|
|
735
|
-
// if (prop && prop.getKind() === SyntaxKind.PropertyAssignment) {
|
|
736
|
-
// const elements = prop.getFirstDescendantByKind(SyntaxKind.ArrayLiteralExpression);
|
|
737
|
-
// elements?.getElements().forEach(el => {
|
|
738
|
-
// const text = el.getText();
|
|
739
|
-
// if (filesToDelete.some(file => text.toLowerCase().includes(file.split('.')[0]))) {
|
|
740
|
-
// // @ts-ignore
|
|
741
|
-
// el.remove();
|
|
742
|
-
// }
|
|
743
|
-
// });
|
|
744
|
-
// }
|
|
745
|
-
// }
|
|
746
|
-
// }
|
|
747
|
-
|
|
748
|
-
// // Save changes
|
|
749
|
-
// sourceFile.saveSync();
|
|
750
|
-
|
|
751
|
-
// Run seeder to reflect the removal.
|
|
713
|
+
// <moduleName>.module.ts | Remove all references and imports of the deleted model files. | Automatic
|
|
714
|
+
if (modulePath) {
|
|
715
|
+
const moduleFilePath = path.resolve(modulePath, `${dasherize(modelEntity.module?.name)}.module.ts`);
|
|
716
|
+
this.logger.log(`Removing model '${modelEntity.singularName}' references from module file: ${moduleFilePath}`);
|
|
717
|
+
try {
|
|
718
|
+
this.solidTsMorphService.begin();
|
|
719
|
+
const modelPathSegment = `/${dasherize(modelEntity.singularName)}.`;
|
|
720
|
+
const { removedIdentifiers } = this.solidTsMorphService.removeImports(
|
|
721
|
+
moduleFilePath,
|
|
722
|
+
spec => spec.includes(modelPathSegment)
|
|
723
|
+
);
|
|
724
|
+
this.solidTsMorphService.removeModuleMembers(moduleFilePath, removedIdentifiers);
|
|
725
|
+
await this.solidTsMorphService.commit();
|
|
726
|
+
} catch (error) {
|
|
727
|
+
this.solidTsMorphService.rollback();
|
|
728
|
+
this.logger.error(`Failed to clean up module file for model '${modelEntity.singularName}':`, error);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
752
731
|
|
|
753
732
|
// - | Drop database table | Removes the database table from the DB, this is a very risky step. Best to review all relations to other models etc and then do this manually | Manual (X)
|
|
754
733
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
1
|
+
import { Inject, Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { CACHE_MANAGER } from '@nestjs/cache-manager';
|
|
2
3
|
import { ModuleRef } from "@nestjs/core";
|
|
3
4
|
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
5
|
+
import { Cache } from 'cache-manager';
|
|
4
6
|
import { CRUDService } from 'src/services/crud.service';
|
|
7
|
+
import { shouldUseCache } from 'src/helpers/cache.helper';
|
|
5
8
|
import { EntityManager, In } from 'typeorm';
|
|
6
9
|
|
|
7
10
|
|
|
@@ -10,42 +13,92 @@ import { PermissionMetadata } from '../entities/permission-metadata.entity';
|
|
|
10
13
|
|
|
11
14
|
@Injectable()
|
|
12
15
|
export class PermissionMetadataService extends CRUDService<PermissionMetadata> {
|
|
16
|
+
private readonly logger = new Logger(PermissionMetadataService.name);
|
|
13
17
|
constructor(
|
|
14
18
|
@InjectEntityManager()
|
|
15
19
|
readonly entityManager: EntityManager,
|
|
16
20
|
// @InjectRepository(PermissionMetadata, 'default')
|
|
17
21
|
// readonly repo: Repository<PermissionMetadata>,
|
|
18
22
|
readonly repo: PermissionMetadataRepository,
|
|
19
|
-
readonly moduleRef: ModuleRef
|
|
20
|
-
|
|
23
|
+
readonly moduleRef: ModuleRef,
|
|
24
|
+
@Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
|
|
21
25
|
) {
|
|
22
26
|
super(entityManager, repo, 'permissionMetadata', 'solid-core',moduleRef);
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
private buildPermissionsByRoleCacheKey(roleName: string): string {
|
|
30
|
+
return `permissions:role:${roleName}`;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async findAllUsingRoles(roles: string[]): Promise<PermissionMetadata[]> {
|
|
34
|
+
const useCache = shouldUseCache();
|
|
35
|
+
const cached: PermissionMetadata[] = [];
|
|
36
|
+
const uncachedRoles: string[] = [];
|
|
25
37
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
if (useCache) {
|
|
39
|
+
for (const role of roles) {
|
|
40
|
+
const cacheKey = this.buildPermissionsByRoleCacheKey(role);
|
|
41
|
+
const hit = await this.cacheManager.get<PermissionMetadata[]>(cacheKey);
|
|
42
|
+
if (hit) {
|
|
43
|
+
// this.logger.debug(`Cache hit for findAllUsingRoles: key=${cacheKey}`);
|
|
44
|
+
cached.push(...hit);
|
|
45
|
+
} else {
|
|
46
|
+
// this.logger.debug(`Cache miss for findAllUsingRoles: key=${cacheKey}`);
|
|
47
|
+
uncachedRoles.push(role);
|
|
31
48
|
}
|
|
32
|
-
}
|
|
33
|
-
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
uncachedRoles.push(...roles);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (uncachedRoles.length === 0) {
|
|
55
|
+
return cached;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fromDb = await this.repo.find({
|
|
59
|
+
where: { roles: { name: In(uncachedRoles) } },
|
|
60
|
+
relations: { roles: true },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (useCache) {
|
|
64
|
+
for (const role of uncachedRoles) {
|
|
65
|
+
const permsForRole = fromDb.filter(p => p.roles?.some(r => r.name === role));
|
|
66
|
+
await this.cacheManager.set(this.buildPermissionsByRoleCacheKey(role), permsForRole);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const seen = new Set<number>();
|
|
71
|
+
return [...cached, ...fromDb].filter(p => {
|
|
72
|
+
if (seen.has(p.id)) return false;
|
|
73
|
+
seen.add(p.id);
|
|
74
|
+
return true;
|
|
34
75
|
});
|
|
35
76
|
}
|
|
36
77
|
|
|
37
|
-
permissionExistsInRole(role: string, permission: string
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
78
|
+
async permissionExistsInRole(role: string, permission: string): Promise<PermissionMetadata[]> {
|
|
79
|
+
const useCache = shouldUseCache();
|
|
80
|
+
const cacheKey = this.buildPermissionsByRoleCacheKey(role);
|
|
81
|
+
|
|
82
|
+
if (useCache) {
|
|
83
|
+
const hit = await this.cacheManager.get<PermissionMetadata[]>(cacheKey);
|
|
84
|
+
if (hit) {
|
|
85
|
+
// this.logger.debug(`Cache hit for permissionExistsInRole: key=${cacheKey}`);
|
|
86
|
+
return hit.filter(p => p.name === permission);
|
|
87
|
+
}
|
|
88
|
+
// this.logger.debug(`Cache miss for permissionExistsInRole: key=${cacheKey}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const fromDb = await this.repo.find({
|
|
92
|
+
where: { roles: { name: role } },
|
|
93
|
+
relations: { roles: true },
|
|
46
94
|
});
|
|
95
|
+
|
|
96
|
+
if (useCache) {
|
|
97
|
+
await this.cacheManager.set(cacheKey, fromDb);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return fromDb.filter(p => p.name === permission);
|
|
47
101
|
}
|
|
48
102
|
|
|
49
103
|
}
|
|
50
104
|
|
|
51
|
-
|
|
@@ -89,9 +89,15 @@ export abstract class DatabaseSubscriber<T> implements OnModuleInit, QueueSubscr
|
|
|
89
89
|
const defaultBroker = process.env.QUEUES_DEFAULT_BROKER || 'database';
|
|
90
90
|
const solidCliRunning = process.env.SOLID_CLI_RUNNING || "false";
|
|
91
91
|
const queueNameRegex = (process.env.QUEUES_QUEUE_NAME_REGEX_TO_ENABLE || '').trim();
|
|
92
|
+
const roleAllowed = ['both', 'subscriber'].includes(this.serviceRole);
|
|
93
|
+
|
|
94
|
+
if (!roleAllowed) {
|
|
95
|
+
this.logger.log(`DatabaseSubscriber is disabled because QUEUES_SERVICE_ROLE is "${this.serviceRole}". Expected "both" or "subscriber".`);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
92
98
|
|
|
93
99
|
// we will start subscriber only if the current service role is subscriber.
|
|
94
|
-
if (
|
|
100
|
+
if (defaultBroker === 'database' && solidCliRunning === "false") {
|
|
95
101
|
const options = this.options();
|
|
96
102
|
const queueName = options.queueName;
|
|
97
103
|
|
|
@@ -37,7 +37,7 @@ export class PublisherFactory<T> {
|
|
|
37
37
|
|
|
38
38
|
// type safe
|
|
39
39
|
const typedActualPublisher: QueuePublisher<T> = actualPublisherToUse.instance;
|
|
40
|
-
this.logger.debug(`Resolved publisher with name ${actualPublisherToUse.name}, and with options: ${JSON.stringify(typedActualPublisher.options())}`);
|
|
40
|
+
// this.logger.debug(`Resolved publisher with name ${actualPublisherToUse.name}, and with options: ${JSON.stringify(typedActualPublisher.options())}`);
|
|
41
41
|
|
|
42
42
|
return typedActualPublisher.publish(message);
|
|
43
43
|
}
|
|
@@ -34,6 +34,10 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
|
|
|
34
34
|
|
|
35
35
|
abstract options(): QueuesModuleOptions;
|
|
36
36
|
|
|
37
|
+
protected shouldPersistToDatabase(): boolean {
|
|
38
|
+
return this.options().persistToDatabase ?? true;
|
|
39
|
+
}
|
|
40
|
+
|
|
37
41
|
private async ensureConnectionAndChannel(): Promise<amqp.Channel> {
|
|
38
42
|
if (this.channel) {
|
|
39
43
|
return this.channel;
|
|
@@ -170,7 +174,9 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
|
|
|
170
174
|
message.messageId = uuidv4();
|
|
171
175
|
|
|
172
176
|
// Save the message to the DB so that we can then change its status in the subscriber...
|
|
173
|
-
|
|
177
|
+
if (this.shouldPersistToDatabase()) {
|
|
178
|
+
await this.persistToDatabase(namespacedQueueName, message);
|
|
179
|
+
}
|
|
174
180
|
|
|
175
181
|
// wait for the channel to confirm
|
|
176
182
|
try {
|
|
@@ -199,7 +205,7 @@ export abstract class RabbitMqPublisher<T> implements OnModuleDestroy, QueuePubl
|
|
|
199
205
|
|
|
200
206
|
private async persistToDatabase(queueName: string, message: QueueMessage<T>) {
|
|
201
207
|
|
|
202
|
-
//
|
|
208
|
+
// make an entry in the relevant database table, generate a unique id earlier.
|
|
203
209
|
try {
|
|
204
210
|
// 1. resolve the queue first
|
|
205
211
|
const mqMessageQueue = await this.mqMessageQueueService.resolveQueue(queueName);
|