@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
|
@@ -3,10 +3,11 @@ import { Entity, Column, JoinColumn, ManyToOne, Index } from 'typeorm';
|
|
|
3
3
|
import { User } from 'src/entities/user.entity';
|
|
4
4
|
import { ModelMetadata } from 'src/entities/model-metadata.entity';
|
|
5
5
|
import { ViewMetadata } from 'src/entities/view-metadata.entity'
|
|
6
|
+
import { getColumnType } from 'src/helpers/typeorm-db-helper';
|
|
6
7
|
|
|
7
8
|
@Entity("ss_saved_fitlers")
|
|
8
9
|
export class SavedFilters extends CommonEntity {
|
|
9
|
-
@Column({
|
|
10
|
+
@Column({ nullable: true, ...getColumnType('longText') })
|
|
10
11
|
filterQueryJson: any;
|
|
11
12
|
|
|
12
13
|
@Index({ unique: true })
|
|
@@ -28,7 +29,7 @@ export class SavedFilters extends CommonEntity {
|
|
|
28
29
|
@JoinColumn()
|
|
29
30
|
view: ViewMetadata;
|
|
30
31
|
|
|
31
|
-
@Column({ name: "description",
|
|
32
|
+
@Column({ name: "description", nullable: true })
|
|
32
33
|
description: string;
|
|
33
34
|
|
|
34
35
|
@Column({ nullable: true, default: false })
|
|
@@ -2,6 +2,7 @@ import { CommonEntity } from 'src/entities/common.entity';
|
|
|
2
2
|
import { ModelMetadata } from 'src/entities/model-metadata.entity';
|
|
3
3
|
import { RoleMetadata } from 'src/entities/role-metadata.entity';
|
|
4
4
|
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
|
|
5
|
+
import { getColumnType } from 'src/helpers/typeorm-db-helper';
|
|
5
6
|
|
|
6
7
|
@Entity("ss_security_rule")
|
|
7
8
|
export class SecurityRule extends CommonEntity {
|
|
@@ -22,7 +23,7 @@ export class SecurityRule extends CommonEntity {
|
|
|
22
23
|
@JoinColumn()
|
|
23
24
|
modelMetadata: ModelMetadata;
|
|
24
25
|
|
|
25
|
-
@Column({
|
|
26
|
+
@Column({ ...getColumnType('longText'), nullable: true })
|
|
26
27
|
securityRuleConfig: any;
|
|
27
28
|
|
|
28
29
|
@Column({ type: "varchar", nullable: true })
|
|
@@ -12,7 +12,7 @@ export class SmsTemplate extends CommonEntity {
|
|
|
12
12
|
body: string;
|
|
13
13
|
@Column({ type: "varchar", nullable: true })
|
|
14
14
|
smsProviderTemplateId: string;
|
|
15
|
-
@Column({ name: "description",
|
|
15
|
+
@Column({ name: "description", nullable: true })
|
|
16
16
|
description: string;
|
|
17
17
|
@Column({ name: "active", nullable: true, default: true })
|
|
18
18
|
active: boolean = true;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommonEntity } from 'src/entities/common.entity'
|
|
2
2
|
import { Entity, JoinColumn, ManyToOne, Index, Column } from 'typeorm';
|
|
3
|
+
import { getColumnType } from 'src/helpers/typeorm-db-helper';
|
|
3
4
|
import { ViewMetadata } from 'src/entities/view-metadata.entity';
|
|
4
5
|
import { User } from 'src/entities/user.entity'
|
|
5
6
|
|
|
@@ -9,7 +10,7 @@ export class UserViewMetadata extends CommonEntity {
|
|
|
9
10
|
@ManyToOne(() => User, { nullable: false })
|
|
10
11
|
@JoinColumn()
|
|
11
12
|
user: User;
|
|
12
|
-
@Column({ name: "layout",
|
|
13
|
+
@Column({ name: "layout", nullable: true, ...getColumnType('longText') })
|
|
13
14
|
layout: any = "{}";
|
|
14
15
|
@Index()
|
|
15
16
|
@ManyToOne(() => ViewMetadata, { nullable: false })
|
|
@@ -11,109 +11,144 @@ export class User extends CommonEntity {
|
|
|
11
11
|
@Column({ type: "varchar", nullable: true })
|
|
12
12
|
@Expose()
|
|
13
13
|
fullName: string;
|
|
14
|
+
|
|
14
15
|
@Index({ unique: true })
|
|
15
16
|
@Column({ type: "varchar" })
|
|
16
17
|
@Expose()
|
|
17
18
|
username: string;
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
@Index()
|
|
19
21
|
@Column({ type: "varchar", nullable: true })
|
|
20
22
|
@Expose()
|
|
21
23
|
email: string;
|
|
22
|
-
|
|
24
|
+
|
|
25
|
+
@Index()
|
|
23
26
|
@Column({ type: "varchar", nullable: true })
|
|
24
27
|
@Expose()
|
|
25
28
|
mobile: string;
|
|
29
|
+
|
|
26
30
|
@Column({ type: "varchar", nullable: true })
|
|
27
31
|
// don't send to client
|
|
28
32
|
password: string;
|
|
33
|
+
|
|
29
34
|
@Column({ nullable: true, default: true })
|
|
30
35
|
@Expose()
|
|
31
36
|
forcePasswordChange: boolean = true;
|
|
37
|
+
|
|
32
38
|
@Column({ type: "varchar", default: "local" })
|
|
33
39
|
// don't send to client
|
|
34
40
|
lastLoginProvider: string = "local";
|
|
41
|
+
|
|
35
42
|
@Column({ type: "varchar", nullable: true })
|
|
36
43
|
// don't send to client (test)
|
|
37
44
|
accessCode: string;
|
|
45
|
+
|
|
38
46
|
@Column({ type: "varchar", nullable: true })
|
|
39
47
|
// don't send to client
|
|
40
48
|
googleAccessToken: string;
|
|
49
|
+
|
|
41
50
|
@Column({ type: "varchar", nullable: true })
|
|
42
51
|
// don't send to client
|
|
43
52
|
googleId: string;
|
|
53
|
+
|
|
44
54
|
@Column({ type: "varchar", nullable: true })
|
|
45
55
|
// don't send to client
|
|
46
56
|
googleProfilePicture: string;
|
|
57
|
+
|
|
47
58
|
@Column({ default: true })
|
|
48
59
|
@Expose()
|
|
49
60
|
active: boolean = true;
|
|
61
|
+
|
|
50
62
|
@Column({ nullable: true })
|
|
51
63
|
// don't send to client
|
|
52
64
|
forgotPasswordConfirmedAt: Date;
|
|
65
|
+
|
|
53
66
|
@Column({ type: "varchar", nullable: true })
|
|
54
67
|
// don't send to client
|
|
55
68
|
verificationTokenOnForgotPassword: string;
|
|
69
|
+
|
|
56
70
|
@Column({ nullable: true })
|
|
57
71
|
// don't send to client
|
|
58
72
|
verificationTokenOnForgotPasswordExpiresAt: Date;
|
|
73
|
+
|
|
59
74
|
@Column({ nullable: true })
|
|
60
75
|
// don't send to client
|
|
61
76
|
emailVerifiedOnRegistrationAt: Date;
|
|
77
|
+
|
|
62
78
|
@Column({ type: "varchar", nullable: true })
|
|
63
79
|
// don't send to client
|
|
64
80
|
emailVerificationTokenOnRegistration: string;
|
|
81
|
+
|
|
65
82
|
@Column({ nullable: true })
|
|
66
83
|
// don't send to client
|
|
67
84
|
emailVerificationTokenOnRegistrationExpiresAt: Date;
|
|
85
|
+
|
|
68
86
|
@Column({ nullable: true })
|
|
69
87
|
// don't send to client
|
|
70
88
|
mobileVerifiedOnRegistrationAt: Date;
|
|
89
|
+
|
|
71
90
|
@Column({ type: "varchar", nullable: true })
|
|
72
91
|
// don't send to client
|
|
73
92
|
mobileVerificationTokenOnRegistration: string;
|
|
93
|
+
|
|
74
94
|
@Column({ nullable: true })
|
|
75
95
|
// don't send to client
|
|
76
96
|
mobileVerificationTokenOnRegistrationExpiresAt: Date;
|
|
97
|
+
|
|
77
98
|
@Column({ nullable: true })
|
|
78
99
|
// don't send to client
|
|
79
100
|
emailVerifiedOnLoginAt: Date;
|
|
101
|
+
|
|
80
102
|
@Column({ type: "varchar", nullable: true })
|
|
81
103
|
// don't send to client
|
|
82
104
|
emailVerificationTokenOnLogin: string;
|
|
105
|
+
|
|
83
106
|
@Column({ nullable: true })
|
|
84
107
|
// don't send to client
|
|
85
108
|
emailVerificationTokenOnLoginExpiresAt: Date;
|
|
109
|
+
|
|
86
110
|
@Column({ nullable: true })
|
|
87
111
|
// don't send to client
|
|
88
112
|
mobileVerifiedOnLoginAt: Date;
|
|
113
|
+
|
|
89
114
|
@Column({ type: "varchar", nullable: true })
|
|
90
115
|
// don't send to client
|
|
91
116
|
mobileVerificationTokenOnLogin: string;
|
|
117
|
+
|
|
92
118
|
@Column({ nullable: true })
|
|
93
119
|
// don't send to client
|
|
94
120
|
mobileVerificationTokenOnLoginExpiresAt: Date;
|
|
121
|
+
|
|
95
122
|
@Column({ type: "varchar", nullable: true })
|
|
96
123
|
@Expose()
|
|
97
124
|
customPayload: string;
|
|
125
|
+
|
|
98
126
|
@ManyToMany(() => RoleMetadata, roleMetadata => roleMetadata.users, { cascade: true })
|
|
99
127
|
@JoinTable()
|
|
100
128
|
@Expose()
|
|
101
129
|
roles: RoleMetadata[];
|
|
130
|
+
|
|
102
131
|
@OneToMany(() => UserViewMetadata, userViewMetadata => userViewMetadata.user, { cascade: true })
|
|
103
132
|
// don't send to client
|
|
104
133
|
userViewMetadata: UserViewMetadata[];
|
|
134
|
+
|
|
105
135
|
// dont send to client
|
|
106
136
|
@Column({ type: "varchar", default: "bcrypt" })
|
|
107
137
|
passwordScheme: string;
|
|
138
|
+
|
|
108
139
|
// dont send to client
|
|
109
140
|
@Column({ type: "int", default: 1 })
|
|
110
141
|
passwordSchemeVersion: number;
|
|
142
|
+
|
|
111
143
|
// dont send to client
|
|
112
144
|
@Column({ nullable: true })
|
|
113
145
|
rehashedAt: Date;
|
|
146
|
+
|
|
114
147
|
// dont send to client
|
|
115
148
|
@Column({ type: "int", default: 0 })
|
|
116
149
|
failedLoginAttempts: number = 0;
|
|
150
|
+
|
|
117
151
|
@Expose()
|
|
118
152
|
_media: any;
|
|
153
|
+
|
|
119
154
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommonEntity } from "src/entities/common.entity"
|
|
2
2
|
import { Entity, Column, ManyToOne, Index, JoinColumn, OneToMany } from "typeorm";
|
|
3
|
+
import { getColumnType } from 'src/helpers/typeorm-db-helper';
|
|
3
4
|
import { ModuleMetadata } from 'src/entities/module-metadata.entity';
|
|
4
5
|
import { ModelMetadata } from 'src/entities/model-metadata.entity';
|
|
5
6
|
import { UserViewMetadata } from 'src/entities/user-view-metadata.entity'
|
|
@@ -16,9 +17,11 @@ export class ViewMetadata extends CommonEntity {
|
|
|
16
17
|
@Column({ name: "type", type: "varchar" })
|
|
17
18
|
type: string;
|
|
18
19
|
|
|
20
|
+
//TODO: To make this truly cross db compatible, we should avoid setting a db type
|
|
19
21
|
@Column({ name: "context", type: "text" })
|
|
20
22
|
context: any = "{}";
|
|
21
23
|
|
|
24
|
+
//TODO: To make this truly cross db compatible, we should avoid setting a db type
|
|
22
25
|
@Column({ name: "layout", type: "text" })
|
|
23
26
|
layout: any;
|
|
24
27
|
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { ValidationPipe } from '@nestjs/common';
|
|
2
|
+
import { NestFactory } from '@nestjs/core';
|
|
3
|
+
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
4
|
+
import { NextFunction, Request, Response } from 'express';
|
|
5
|
+
import helmet from 'helmet';
|
|
6
|
+
import qs from 'qs';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { resolve } from 'path';
|
|
9
|
+
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';
|
|
10
|
+
import { CommandFactory } from 'nest-commander';
|
|
11
|
+
import { WrapResponseInterceptor } from '../interceptors/wrap-response.interceptor';
|
|
12
|
+
import { buildDefaultCorsOptions } from './cors.helper';
|
|
13
|
+
import { buildDefaultSecurityHeaderOptions, buildPermissionsPolicyHeader, PermissionsPolicyConfig } from './security.helper';
|
|
14
|
+
import { parseBooleanEnv } from './environment.helper';
|
|
15
|
+
|
|
16
|
+
// ---- Shared process handlers ----
|
|
17
|
+
|
|
18
|
+
function registerGlobalProcessHandlers() {
|
|
19
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
20
|
+
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
process.on('uncaughtException', (err) => {
|
|
24
|
+
console.error('Uncaught Exception thrown:', err);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Suppress pg deprecation warning caused by TypeORM's internal query scheduling
|
|
28
|
+
process.on('warning', (warning) => {
|
|
29
|
+
if (warning.name === 'DeprecationWarning' && (warning.message.includes('client.query()') || warning.message.includes('punycode'))) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
console.warn(warning);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---- HTTP server bootstrap ----
|
|
37
|
+
|
|
38
|
+
export interface SolidSwaggerOptions {
|
|
39
|
+
title?: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
version?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SolidBootstrapOptions {
|
|
45
|
+
/** Global API prefix. Defaults to 'api'. Set to '' to disable. */
|
|
46
|
+
globalPrefix?: string;
|
|
47
|
+
/** Swagger configuration. Set to false to disable Swagger entirely. */
|
|
48
|
+
swagger?: SolidSwaggerOptions | false;
|
|
49
|
+
/** Permissions-Policy header overrides (merged with defaults). */
|
|
50
|
+
permissionsPolicyOverrides?: Partial<PermissionsPolicyConfig>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Bootstraps a SolidX NestJS HTTP application with sensible defaults:
|
|
55
|
+
* security headers, CORS, Winston logger, ValidationPipe,
|
|
56
|
+
* WrapResponseInterceptor, qs deep query parsing, Swagger, and the
|
|
57
|
+
* pg BIGINT type parser.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* // main.ts
|
|
61
|
+
* bootstrapSolidApp(() => AppModule.forRoot(), {
|
|
62
|
+
* swagger: { title: 'My API', description: 'My API description' },
|
|
63
|
+
* });
|
|
64
|
+
*/
|
|
65
|
+
export async function bootstrapSolidApp(
|
|
66
|
+
appModuleFactory: () => Promise<any>,
|
|
67
|
+
options: SolidBootstrapOptions = {},
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
registerGlobalProcessHandlers();
|
|
70
|
+
|
|
71
|
+
const { globalPrefix = 'api', swagger = {}, permissionsPolicyOverrides = {} } = options;
|
|
72
|
+
|
|
73
|
+
const appModule = await appModuleFactory();
|
|
74
|
+
const app = await NestFactory.create(appModule);
|
|
75
|
+
|
|
76
|
+
const apiEnabled = parseBooleanEnv('API_ENABLED', true);
|
|
77
|
+
|
|
78
|
+
if (!apiEnabled) {
|
|
79
|
+
await app.init();
|
|
80
|
+
app
|
|
81
|
+
.get(WINSTON_MODULE_NEST_PROVIDER)
|
|
82
|
+
.log('API server disabled via API_ENABLED=false. Skipping HTTP listen.', 'Bootstrap');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Health check at root path
|
|
87
|
+
const server = app.getHttpAdapter().getInstance();
|
|
88
|
+
server.get('/', (_req, res) => res.status(200).send('SOLID OK'));
|
|
89
|
+
|
|
90
|
+
// Security headers
|
|
91
|
+
app.use(helmet(buildDefaultSecurityHeaderOptions()));
|
|
92
|
+
|
|
93
|
+
// Permissions-Policy header
|
|
94
|
+
app.use((_req: Request, res: Response, next: NextFunction) => {
|
|
95
|
+
res.setHeader('Permissions-Policy', buildPermissionsPolicyHeader(permissionsPolicyOverrides));
|
|
96
|
+
next();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Winston logger
|
|
100
|
+
app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));
|
|
101
|
+
|
|
102
|
+
const port = process.env.PORT || 3000;
|
|
103
|
+
|
|
104
|
+
if (globalPrefix) {
|
|
105
|
+
app.setGlobalPrefix(globalPrefix);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// qs-based deep query parsing (dot notation, nested objects, arrays)
|
|
109
|
+
app.use((req: Request, _res: Response, next: NextFunction) => {
|
|
110
|
+
if (req.query) {
|
|
111
|
+
req.query = qs.parse(req.url.split('?')[1], {
|
|
112
|
+
allowDots: true,
|
|
113
|
+
depth: 20,
|
|
114
|
+
arrayLimit: 100,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
next();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Global ValidationPipe
|
|
121
|
+
app.useGlobalPipes(
|
|
122
|
+
new ValidationPipe({
|
|
123
|
+
transform: true,
|
|
124
|
+
transformOptions: { enableImplicitConversion: true },
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
// Swagger
|
|
129
|
+
if (swagger !== false) {
|
|
130
|
+
const { title = 'Solid Starters', description = 'Solid Starters API', version = '1.0' } = swagger;
|
|
131
|
+
const swaggerConfig = new DocumentBuilder()
|
|
132
|
+
.setTitle(title)
|
|
133
|
+
.setDescription(description)
|
|
134
|
+
.setVersion(version)
|
|
135
|
+
.setExternalDoc('Postman Collection', '/docs-json')
|
|
136
|
+
.addBearerAuth(
|
|
137
|
+
{
|
|
138
|
+
description: 'Please enter token in following format: Bearer <JWT>',
|
|
139
|
+
name: 'Authorization',
|
|
140
|
+
bearerFormat: 'Bearer',
|
|
141
|
+
scheme: 'Bearer',
|
|
142
|
+
type: 'http',
|
|
143
|
+
in: 'Header',
|
|
144
|
+
},
|
|
145
|
+
'jwt',
|
|
146
|
+
)
|
|
147
|
+
.build();
|
|
148
|
+
const document = SwaggerModule.createDocument(app, swaggerConfig);
|
|
149
|
+
SwaggerModule.setup('/docs', app, document);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Global interceptor
|
|
153
|
+
app.useGlobalInterceptors(new WrapResponseInterceptor());
|
|
154
|
+
|
|
155
|
+
// CORS
|
|
156
|
+
app.enableCors(buildDefaultCorsOptions());
|
|
157
|
+
|
|
158
|
+
// Fix pg returning BIGINT columns as strings
|
|
159
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
160
|
+
const types = require('pg').types;
|
|
161
|
+
types.setTypeParser(types.builtins.INT8, (val: string) => parseInt(val));
|
|
162
|
+
|
|
163
|
+
await app.listen(port);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ---- CLI bootstrap ----
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Bootstraps a SolidX NestJS CLI application using nest-commander.
|
|
170
|
+
* Handles verbose flag stripping, project root validation, and clean process exit.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* // main-cli.ts
|
|
174
|
+
* #!/usr/bin/env node
|
|
175
|
+
* import { bootstrapSolidCli } from '@solidxai/core';
|
|
176
|
+
* import { AppModule } from './app.module';
|
|
177
|
+
*
|
|
178
|
+
* bootstrapSolidCli(() => AppModule.forRoot());
|
|
179
|
+
*/
|
|
180
|
+
export async function bootstrapSolidCli(
|
|
181
|
+
appModuleFactory: () => Promise<any>,
|
|
182
|
+
): Promise<void> {
|
|
183
|
+
registerGlobalProcessHandlers();
|
|
184
|
+
|
|
185
|
+
process.on('exit', (code) => {
|
|
186
|
+
if (code !== 0) {
|
|
187
|
+
console.error(`Exiting with error status code: ${code}`);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Validate that cwd is a valid Solid API project
|
|
192
|
+
const packageJsonPath = resolve(process.cwd(), 'package.json');
|
|
193
|
+
if (!existsSync(packageJsonPath)) {
|
|
194
|
+
console.error('Does not seem to be a valid solid-api project.');
|
|
195
|
+
console.error('Exit reason: missing package.json in the current directory.');
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Strip --verbose / -v before nest-commander processes argv
|
|
200
|
+
const showLogs = process.argv.includes('--verbose') || process.argv.includes('-v');
|
|
201
|
+
for (const flag of ['--verbose', '-v']) {
|
|
202
|
+
const idx = process.argv.indexOf(flag);
|
|
203
|
+
if (idx !== -1) process.argv.splice(idx, 1);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const appModule = await appModuleFactory();
|
|
207
|
+
process.env.SOLID_CLI_RUNNING = 'true';
|
|
208
|
+
|
|
209
|
+
// @ts-ignore
|
|
210
|
+
const app = await CommandFactory.createWithoutRunning(appModule, {
|
|
211
|
+
logger: showLogs ? ['debug', 'error', 'fatal', 'log', 'verbose', 'warn'] : false,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
await CommandFactory.runApplication(app);
|
|
216
|
+
} catch (e) {
|
|
217
|
+
console.error('CLI exited abruptly due to an error:', e);
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
process.exit(0);
|
|
222
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { Logger } from '@nestjs/common';
|
|
1
2
|
import { CorsOptions } from 'cors';
|
|
2
3
|
|
|
4
|
+
const logger = new Logger('CorsHelper');
|
|
5
|
+
|
|
3
6
|
/** Build CorsOptions from env; supports wildcards like https://*.example.com */
|
|
4
7
|
export function buildDefaultCorsOptions(): CorsOptions {
|
|
5
8
|
const rawOrigins = process.env.SECURITY_CORS_ORIGINS ?? '*';
|
|
9
|
+
logger.log(`CORS allowed origins: ${rawOrigins}`);
|
|
6
10
|
|
|
7
11
|
const allowed = rawOrigins.split(',').map(s => s.trim()).filter(Boolean);
|
|
8
12
|
|
|
@@ -18,17 +22,33 @@ export function buildDefaultCorsOptions(): CorsOptions {
|
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
const matchers = allowed.map(patternToRegex);
|
|
21
|
-
|
|
22
|
-
matchers.length > 0 && matchers.some(rx => rx.test(origin));
|
|
25
|
+
logger.log(`CORS regexes: ${matchers.map(r => r.toString()).join(', ')}`);
|
|
23
26
|
|
|
24
27
|
return {
|
|
25
28
|
origin: (origin, cb) => {
|
|
26
|
-
if (!origin)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
if (!origin) {
|
|
30
|
+
logger.debug('CORS origin callback skipped regex evaluation because origin was empty');
|
|
31
|
+
// allow no-origin (CLI/mobile/internal)
|
|
32
|
+
return cb(null, true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const matchingRegex = matchers.find(rx => rx.test(origin));
|
|
36
|
+
if (matchingRegex) {
|
|
37
|
+
logger.debug(`CORS origin matched: origin=${origin}; regex=${matchingRegex.toString()}`);
|
|
38
|
+
return cb(null, true);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
logger.debug(`CORS origin did not match any regex: origin=${origin}; regexes=${matchers.map(r => r.toString()).join(', ')}`);
|
|
42
|
+
return cb(new Error(`Origin ${origin} not allowed by CORS. Allowed origins: ${allowed.join(', ')}`), false);
|
|
29
43
|
},
|
|
30
44
|
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
31
45
|
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
32
46
|
credentials: true,
|
|
33
47
|
};
|
|
34
|
-
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// [2026-04-07T08:27:19.943Z] INFO: CORS allowed origins: leadyatra.indusindnipponlife.com
|
|
52
|
+
// [2026-04-07T08:27:19.944Z] INFO: CORS regexes: /^https?:\/\/leadyatra\.indusindnipponlife\.com(?::\d+)?$/i
|
|
53
|
+
// [2026-04-07T08:27:19.947Z] DEBUG: Mounting ClsMiddleware to *
|
|
54
|
+
// [2026-04-07T08:27:19.950Z] INFO: CityMasterController {/api/city-master}:
|
|
@@ -11,6 +11,7 @@ export interface MediaFieldOptions {
|
|
|
11
11
|
fieldName: string | undefined | null;
|
|
12
12
|
mediaMaxSizeKb: number | undefined | null;
|
|
13
13
|
mediaTypes: string[];
|
|
14
|
+
isUpdate: boolean | undefined | null;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
type MediaType = 'image' | 'audio' | 'video' | 'file' | 'pdf';
|
|
@@ -119,25 +120,24 @@ export class MediaFieldCrudManager implements FieldCrudManager {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
validate(dto: any, files: Array<Express.Multer.File>): ValidationError[] {
|
|
122
|
-
const isValidateForUpdate = dto.id !== undefined; //FIXME: This is a hack, since we are using PUT for update. Once we support PATCH, this will be removed
|
|
123
123
|
const fieldFiles = files.filter(file => file.fieldname === this.options.fieldName);
|
|
124
|
-
return this.applyValidations(fieldFiles
|
|
124
|
+
return this.applyValidations(fieldFiles);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
private applyValidations(fieldFiles: Array<Express.Multer.File
|
|
127
|
+
private applyValidations(fieldFiles: Array<Express.Multer.File>): ValidationError[] {
|
|
128
128
|
switch (this.options.type) {
|
|
129
129
|
case SolidMediaType.mediaSingle:
|
|
130
|
-
return this.validateMediaSingle(fieldFiles
|
|
130
|
+
return this.validateMediaSingle(fieldFiles);
|
|
131
131
|
case SolidMediaType.mediaMultiple:
|
|
132
|
-
return this.validateMediaMultiple(fieldFiles
|
|
132
|
+
return this.validateMediaMultiple(fieldFiles);
|
|
133
133
|
default:
|
|
134
134
|
return [];
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
private validateMediaSingle(fieldFiles: Array<Express.Multer.File
|
|
138
|
+
private validateMediaSingle(fieldFiles: Array<Express.Multer.File>): ValidationError[] {
|
|
139
139
|
const errors: ValidationError[] = [];
|
|
140
|
-
if (!
|
|
140
|
+
if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {
|
|
141
141
|
errors.push({
|
|
142
142
|
field: this.options.fieldName,
|
|
143
143
|
error: `${this.options.fieldName} is required`
|
|
@@ -184,9 +184,9 @@ export class MediaFieldCrudManager implements FieldCrudManager {
|
|
|
184
184
|
return errors;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
private validateMediaMultiple(fieldFiles: Array<Express.Multer.File
|
|
187
|
+
private validateMediaMultiple(fieldFiles: Array<Express.Multer.File>): ValidationError[] {
|
|
188
188
|
const errors: ValidationError[] = [];
|
|
189
|
-
if (!
|
|
189
|
+
if (!this.options.isUpdate && this.options.required && fieldFiles.length === 0) {
|
|
190
190
|
errors.push({
|
|
191
191
|
field: this.options.fieldName,
|
|
192
192
|
error: `${this.options.fieldName} is required`
|
|
@@ -7,7 +7,7 @@ export interface SelectionDynamicFieldOptions {
|
|
|
7
7
|
selectionDynamicProvider: string;
|
|
8
8
|
selectionValueType: SelectionValueType;
|
|
9
9
|
required: boolean | undefined | null;
|
|
10
|
-
selectionDynamicProviderCtxt:
|
|
10
|
+
selectionDynamicProviderCtxt: ISelectionProviderContext;
|
|
11
11
|
fieldName: string;
|
|
12
12
|
discoveryService: DiscoveryService;
|
|
13
13
|
isMultiSelect: boolean | undefined | null;
|
|
@@ -85,8 +85,11 @@ export class SelectionDynamicFieldCrudManager implements FieldCrudManager {
|
|
|
85
85
|
private async applyFormatValidations(fieldValue: any): Promise<ValidationError[]> {
|
|
86
86
|
const errors: ValidationError[] = [];
|
|
87
87
|
!this.isValidSelectionValueType(fieldValue, this.options.selectionValueType) ? errors.push({ field: this.options.fieldName, error: 'Field value type is invalid' }) : "no errors";
|
|
88
|
-
const
|
|
89
|
-
|
|
88
|
+
const ctxt = this.options.selectionDynamicProviderCtxt;
|
|
89
|
+
if (ctxt.validateOnSave !== false) {
|
|
90
|
+
const _isValidSelectionValue = await this.isValidSelectionValue(fieldValue, this.options.selectionDynamicProvider, ctxt);
|
|
91
|
+
!_isValidSelectionValue ? errors.push({ field: this.options.fieldName, error: 'Field value is invalid' }) : "no errors";
|
|
92
|
+
}
|
|
90
93
|
return errors;
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -106,11 +109,11 @@ export class SelectionDynamicFieldCrudManager implements FieldCrudManager {
|
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
private async isValidSelectionValue(fieldValue: any, selectionDynamicProvider: string): Promise<boolean> {
|
|
112
|
+
private async isValidSelectionValue(fieldValue: any, selectionDynamicProvider: string, ctxt: ISelectionProviderContext): Promise<boolean> {
|
|
110
113
|
const providerInstance = this.providerInstance<any>(selectionDynamicProvider);
|
|
111
114
|
try {
|
|
112
115
|
// Use the value method first
|
|
113
|
-
const valueOption = await providerInstance.value(fieldValue,
|
|
116
|
+
const valueOption = await providerInstance.value(fieldValue, ctxt);
|
|
114
117
|
if (valueOption && valueOption.value === fieldValue) {
|
|
115
118
|
return true;
|
|
116
119
|
}
|
|
@@ -118,7 +121,7 @@ export class SelectionDynamicFieldCrudManager implements FieldCrudManager {
|
|
|
118
121
|
}
|
|
119
122
|
catch (error) {
|
|
120
123
|
// Use the values method as a fallback, if the value method is not implemented
|
|
121
|
-
const values = await providerInstance.values('',
|
|
124
|
+
const values = await providerInstance.values('', ctxt);
|
|
122
125
|
const isValid = values.some(v => v.value === fieldValue);
|
|
123
126
|
return isValid;
|
|
124
127
|
}
|
|
@@ -5,12 +5,8 @@ import { CommonEntity } from 'src/entities/common.entity';
|
|
|
5
5
|
import { Locale } from 'src/entities/locale.entity';
|
|
6
6
|
import { SecurityRule } from 'src/entities/security-rule.entity';
|
|
7
7
|
import { IScheduledJob } from 'src/services/scheduled-jobs/scheduled-job.interface';
|
|
8
|
-
import { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, IErrorCodeProvider, ISecurityRuleConfigProvider, ISelectionProvider, ISelectionProviderContext, ISolidDatabaseModule
|
|
9
|
-
import { DatasourceType } from 'src/dtos/create-model-metadata.dto';
|
|
8
|
+
import { IDashboardQuestionDataProvider, IDashboardVariableSelectionProvider, IErrorCodeProvider, ISecurityRuleConfigProvider, ISelectionProvider, ISelectionProviderContext, ISolidDatabaseModule } from "../interfaces";
|
|
10
9
|
import { ObjectLiteral } from 'typeorm';
|
|
11
|
-
import { ColumnMetadata } from 'typeorm/metadata/ColumnMetadata';
|
|
12
|
-
import { RelationMetadata } from 'typeorm/metadata/RelationMetadata';
|
|
13
|
-
import { Setting } from 'src/entities/setting.entity';
|
|
14
10
|
|
|
15
11
|
type ControllerMetadata = {
|
|
16
12
|
name: string;
|
|
@@ -86,6 +82,7 @@ export class SolidRegistry {
|
|
|
86
82
|
private securityRuleConfigProviders: Set<InstanceWrapper> = new Set();
|
|
87
83
|
private errorCodeProviders: Set<InstanceWrapper> = new Set();
|
|
88
84
|
private settingsProviders: Set<InstanceWrapper> = new Set();
|
|
85
|
+
private auditableModels: Set<string> = new Set();
|
|
89
86
|
|
|
90
87
|
registerErrorCodeProvider(errorCodeProvider: InstanceWrapper): void {
|
|
91
88
|
this.errorCodeProviders.add(errorCodeProvider);
|
|
@@ -342,6 +339,14 @@ export class SolidRegistry {
|
|
|
342
339
|
});
|
|
343
340
|
}
|
|
344
341
|
|
|
342
|
+
registerAuditableModels(models: Set<string>): void {
|
|
343
|
+
this.auditableModels = models;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
isAuditableModel(modelSingularName: string): boolean {
|
|
347
|
+
return this.auditableModels.has(modelSingularName.toLowerCase());
|
|
348
|
+
}
|
|
349
|
+
|
|
345
350
|
getCommonEntityKeys(): (keyof CommonEntity | 'createdBy' | 'updatedBy')[] {
|
|
346
351
|
return ['id', 'createdAt', 'updatedAt', 'deletedAt', 'createdBy', 'updatedBy', 'deletedTracker', 'localeName', 'defaultEntityLocaleId', 'publishedAt'];
|
|
347
352
|
// return Reflect.getMetadataKeys(CommonEntity.prototype) as (keyof CommonEntity)[];
|