@solidxai/core 0.1.10 → 0.1.11-beta.0
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/dist/controllers/datasource-introspection.controller.d.ts +234 -0
- package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -0
- package/dist/controllers/datasource-introspection.controller.js +98 -0
- package/dist/controllers/datasource-introspection.controller.js.map +1 -0
- package/dist/controllers/datasource-management.controller.d.ts +18 -0
- package/dist/controllers/datasource-management.controller.d.ts.map +1 -0
- package/dist/controllers/datasource-management.controller.js +55 -0
- package/dist/controllers/datasource-management.controller.js.map +1 -0
- package/dist/dtos/create-datasource-management.dto.d.ts +25 -0
- package/dist/dtos/create-datasource-management.dto.d.ts.map +1 -0
- package/dist/dtos/create-datasource-management.dto.js +169 -0
- package/dist/dtos/create-datasource-management.dto.js.map +1 -0
- package/dist/dtos/datasource-introspection-mapping.dto.d.ts +45 -0
- package/dist/dtos/datasource-introspection-mapping.dto.d.ts.map +1 -0
- package/dist/dtos/datasource-introspection-mapping.dto.js +233 -0
- package/dist/dtos/datasource-introspection-mapping.dto.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/datasource-introspection-provider.interface.d.ts +26 -0
- package/dist/interfaces/datasource-introspection-provider.interface.d.ts.map +1 -0
- package/dist/interfaces/datasource-introspection-provider.interface.js +3 -0
- package/dist/interfaces/datasource-introspection-provider.interface.js.map +1 -0
- package/dist/seeders/seed-data/solid-core-metadata.json +21 -0
- package/dist/services/authentication.service.js +1 -1
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-latency-trend-provider.service.d.ts.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-latency-trend-provider.service.js +2 -2
- package/dist/services/dashboard-providers/mq-dashboard-latency-trend-provider.service.js.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-messages-over-time-provider.service.d.ts.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-messages-over-time-provider.service.js +2 -2
- package/dist/services/dashboard-providers/mq-dashboard-messages-over-time-provider.service.js.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-provider-utils.d.ts +3 -0
- package/dist/services/dashboard-providers/mq-dashboard-provider-utils.d.ts.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-provider-utils.js +71 -0
- package/dist/services/dashboard-providers/mq-dashboard-provider-utils.js.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-queue-sla-heatmap-provider.service.d.ts.map +1 -1
- package/dist/services/dashboard-providers/mq-dashboard-queue-sla-heatmap-provider.service.js +3 -3
- package/dist/services/dashboard-providers/mq-dashboard-queue-sla-heatmap-provider.service.js.map +1 -1
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts +11 -0
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts.map +1 -0
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js +181 -0
- package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js.map +1 -0
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts +11 -0
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts.map +1 -0
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js +90 -0
- package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js.map +1 -0
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts +11 -0
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts.map +1 -0
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js +156 -0
- package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js.map +1 -0
- package/dist/services/datasource-introspection.service.d.ts +288 -0
- package/dist/services/datasource-introspection.service.d.ts.map +1 -0
- package/dist/services/datasource-introspection.service.js +1278 -0
- package/dist/services/datasource-introspection.service.js.map +1 -0
- package/dist/services/datasource-management.service.d.ts +60 -0
- package/dist/services/datasource-management.service.d.ts.map +1 -0
- package/dist/services/datasource-management.service.js +461 -0
- package/dist/services/datasource-management.service.js.map +1 -0
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js +19 -0
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts +1 -3
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +47 -15
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/role-metadata.service.d.ts +1 -0
- package/dist/services/role-metadata.service.d.ts.map +1 -1
- package/dist/services/role-metadata.service.js +13 -0
- package/dist/services/role-metadata.service.js.map +1 -1
- package/dist/services/selection-providers/mq-dashboard-message-broker-variable-options-provider.service.d.ts.map +1 -1
- package/dist/services/selection-providers/mq-dashboard-message-broker-variable-options-provider.service.js +2 -3
- package/dist/services/selection-providers/mq-dashboard-message-broker-variable-options-provider.service.js.map +1 -1
- package/dist/services/selection-providers/mq-dashboard-queue-name-variable-options-provider.service.d.ts.map +1 -1
- package/dist/services/selection-providers/mq-dashboard-queue-name-variable-options-provider.service.js +2 -3
- package/dist/services/selection-providers/mq-dashboard-queue-name-variable-options-provider.service.js.map +1 -1
- package/dist/services/setting.service.d.ts +1 -0
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +32 -8
- package/dist/services/setting.service.js.map +1 -1
- package/dist/services/solid-ts-morph.service.d.ts +1 -1
- package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
- 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/package.json +1 -1
- package/src/controllers/datasource-introspection.controller.ts +58 -0
- package/src/controllers/datasource-management.controller.ts +24 -0
- package/src/dtos/create-datasource-management.dto.ts +139 -0
- package/src/dtos/datasource-introspection-mapping.dto.ts +182 -0
- package/src/index.ts +5 -0
- package/src/interfaces/datasource-introspection-provider.interface.ts +28 -0
- package/src/seeders/seed-data/solid-core-metadata.json +22 -1
- package/src/services/authentication.service.ts +1 -1
- package/src/services/dashboard-providers/mq-dashboard-latency-trend-provider.service.ts +9 -4
- package/src/services/dashboard-providers/mq-dashboard-messages-over-time-provider.service.ts +9 -4
- package/src/services/dashboard-providers/mq-dashboard-provider-utils.ts +82 -0
- package/src/services/dashboard-providers/mq-dashboard-queue-sla-heatmap-provider.service.ts +10 -4
- package/src/services/datasource-introspection/mssql-datasource-introspection-provider.service.ts +185 -0
- package/src/services/datasource-introspection/mysql-datasource-introspection-provider.service.ts +95 -0
- package/src/services/datasource-introspection/postgres-datasource-introspection-provider.service.ts +160 -0
- package/src/services/datasource-introspection.service.ts +1536 -0
- package/src/services/datasource-management.service.ts +566 -0
- package/src/services/field-metadata.service.ts +21 -1
- package/src/services/model-metadata.service.ts +50 -13
- package/src/services/role-metadata.service.ts +14 -0
- package/src/services/selection-providers/mq-dashboard-message-broker-variable-options-provider.service.ts +2 -4
- package/src/services/selection-providers/mq-dashboard-queue-name-variable-options-provider.service.ts +2 -4
- package/src/services/setting.service.ts +43 -12
- package/src/services/solid-ts-morph.service.ts +2 -2
- package/src/solid-core.module.ts +16 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Body, Controller, Get, Param, ParseIntPipe, Post, Query } from "@nestjs/common";
|
|
2
|
+
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
|
|
3
|
+
import { DatasourceIntrospectionMappingDto } from "../dtos/datasource-introspection-mapping.dto";
|
|
4
|
+
import { DatasourceIntrospectionService } from "../services/datasource-introspection.service";
|
|
5
|
+
|
|
6
|
+
@Controller("datasource-introspection")
|
|
7
|
+
@ApiTags("Solid Core")
|
|
8
|
+
export class DatasourceIntrospectionController {
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly datasourceIntrospectionService: DatasourceIntrospectionService,
|
|
11
|
+
) { }
|
|
12
|
+
|
|
13
|
+
@ApiBearerAuth("jwt")
|
|
14
|
+
@Get("modules/:moduleId/bootstrap")
|
|
15
|
+
getBootstrap(
|
|
16
|
+
@Param("moduleId", ParseIntPipe) moduleId: number,
|
|
17
|
+
) {
|
|
18
|
+
return this.datasourceIntrospectionService.getBootstrap(moduleId);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@ApiBearerAuth("jwt")
|
|
22
|
+
@Get("modules/:moduleId/tables")
|
|
23
|
+
getTables(
|
|
24
|
+
@Param("moduleId", ParseIntPipe) moduleId: number,
|
|
25
|
+
@Query("datasource") datasourceName: string,
|
|
26
|
+
) {
|
|
27
|
+
return this.datasourceIntrospectionService.getTables(moduleId, datasourceName);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@ApiBearerAuth("jwt")
|
|
31
|
+
@Get("modules/:moduleId/table-detail")
|
|
32
|
+
getTableDetail(
|
|
33
|
+
@Param("moduleId", ParseIntPipe) moduleId: number,
|
|
34
|
+
@Query("datasource") datasourceName: string,
|
|
35
|
+
@Query("table") tableName: string,
|
|
36
|
+
@Query("schema") schema?: string,
|
|
37
|
+
) {
|
|
38
|
+
return this.datasourceIntrospectionService.getTableDetail(moduleId, datasourceName, tableName, schema);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@ApiBearerAuth("jwt")
|
|
42
|
+
@Post("modules/:moduleId/mapping-preview")
|
|
43
|
+
previewMapping(
|
|
44
|
+
@Param("moduleId", ParseIntPipe) moduleId: number,
|
|
45
|
+
@Body() mappingDto: DatasourceIntrospectionMappingDto,
|
|
46
|
+
) {
|
|
47
|
+
return this.datasourceIntrospectionService.previewMapping(moduleId, mappingDto);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ApiBearerAuth("jwt")
|
|
51
|
+
@Post("modules/:moduleId/apply-mapping")
|
|
52
|
+
applyMapping(
|
|
53
|
+
@Param("moduleId", ParseIntPipe) moduleId: number,
|
|
54
|
+
@Body() mappingDto: DatasourceIntrospectionMappingDto,
|
|
55
|
+
) {
|
|
56
|
+
return this.datasourceIntrospectionService.applyMapping(moduleId, mappingDto);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Body, Controller, Get, Post } from "@nestjs/common";
|
|
2
|
+
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
|
|
3
|
+
import { CreateDatasourceManagementDto } from "../dtos/create-datasource-management.dto";
|
|
4
|
+
import { DatasourceManagementService } from "../services/datasource-management.service";
|
|
5
|
+
|
|
6
|
+
@Controller("datasource-management")
|
|
7
|
+
@ApiTags("Solid Core")
|
|
8
|
+
export class DatasourceManagementController {
|
|
9
|
+
constructor(
|
|
10
|
+
private readonly datasourceManagementService: DatasourceManagementService,
|
|
11
|
+
) { }
|
|
12
|
+
|
|
13
|
+
@ApiBearerAuth("jwt")
|
|
14
|
+
@Get()
|
|
15
|
+
findMany() {
|
|
16
|
+
return this.datasourceManagementService.findMany();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@ApiBearerAuth("jwt")
|
|
20
|
+
@Post()
|
|
21
|
+
create(@Body() createDto: CreateDatasourceManagementDto) {
|
|
22
|
+
return this.datasourceManagementService.create(createDto);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
|
2
|
+
import { Type } from "class-transformer";
|
|
3
|
+
import {
|
|
4
|
+
IsBoolean,
|
|
5
|
+
IsIn,
|
|
6
|
+
IsInt,
|
|
7
|
+
IsOptional,
|
|
8
|
+
IsString,
|
|
9
|
+
Matches,
|
|
10
|
+
Max,
|
|
11
|
+
Min,
|
|
12
|
+
} from "class-validator";
|
|
13
|
+
import { DatasourceType } from "./create-model-metadata.dto";
|
|
14
|
+
|
|
15
|
+
export class CreateDatasourceManagementDto {
|
|
16
|
+
@ApiProperty({ description: "Logical datasource key used in generated filenames and env prefixes." })
|
|
17
|
+
@IsString()
|
|
18
|
+
@Matches(/^[a-z][a-z0-9-]*$/, {
|
|
19
|
+
message: "Datasource name must start with a lower-case letter and use only lower-case letters, numbers, or hyphens.",
|
|
20
|
+
})
|
|
21
|
+
name: string;
|
|
22
|
+
|
|
23
|
+
@ApiPropertyOptional({ description: "Human friendly label shown in the admin interface." })
|
|
24
|
+
@IsOptional()
|
|
25
|
+
@IsString()
|
|
26
|
+
displayName?: string;
|
|
27
|
+
|
|
28
|
+
@ApiProperty({ enum: [DatasourceType.postgres, DatasourceType.mysql, DatasourceType.mssql] })
|
|
29
|
+
@IsIn([DatasourceType.postgres, DatasourceType.mysql, DatasourceType.mssql])
|
|
30
|
+
type: DatasourceType;
|
|
31
|
+
|
|
32
|
+
@ApiProperty()
|
|
33
|
+
@IsString()
|
|
34
|
+
host: string;
|
|
35
|
+
|
|
36
|
+
@ApiProperty()
|
|
37
|
+
@Type(() => Number)
|
|
38
|
+
@IsInt()
|
|
39
|
+
@Min(1)
|
|
40
|
+
@Max(65535)
|
|
41
|
+
port: number;
|
|
42
|
+
|
|
43
|
+
@ApiProperty()
|
|
44
|
+
@IsString()
|
|
45
|
+
database: string;
|
|
46
|
+
|
|
47
|
+
@ApiProperty()
|
|
48
|
+
@IsString()
|
|
49
|
+
username: string;
|
|
50
|
+
|
|
51
|
+
@ApiProperty()
|
|
52
|
+
@IsString()
|
|
53
|
+
password: string;
|
|
54
|
+
|
|
55
|
+
@ApiPropertyOptional()
|
|
56
|
+
@IsOptional()
|
|
57
|
+
@Type(() => Boolean)
|
|
58
|
+
@IsBoolean()
|
|
59
|
+
synchronize?: boolean;
|
|
60
|
+
|
|
61
|
+
@ApiPropertyOptional()
|
|
62
|
+
@IsOptional()
|
|
63
|
+
@Type(() => Boolean)
|
|
64
|
+
@IsBoolean()
|
|
65
|
+
logging?: boolean;
|
|
66
|
+
|
|
67
|
+
@ApiPropertyOptional()
|
|
68
|
+
@IsOptional()
|
|
69
|
+
@Type(() => Boolean)
|
|
70
|
+
@IsBoolean()
|
|
71
|
+
ssl?: boolean;
|
|
72
|
+
|
|
73
|
+
@ApiPropertyOptional()
|
|
74
|
+
@IsOptional()
|
|
75
|
+
@Type(() => Boolean)
|
|
76
|
+
@IsBoolean()
|
|
77
|
+
sslRejectUnauthorized?: boolean;
|
|
78
|
+
|
|
79
|
+
@ApiPropertyOptional()
|
|
80
|
+
@IsOptional()
|
|
81
|
+
@Type(() => Number)
|
|
82
|
+
@IsInt()
|
|
83
|
+
@Min(0)
|
|
84
|
+
poolMax?: number;
|
|
85
|
+
|
|
86
|
+
@ApiPropertyOptional()
|
|
87
|
+
@IsOptional()
|
|
88
|
+
@Type(() => Number)
|
|
89
|
+
@IsInt()
|
|
90
|
+
@Min(0)
|
|
91
|
+
connectionTimeoutMs?: number;
|
|
92
|
+
|
|
93
|
+
@ApiPropertyOptional()
|
|
94
|
+
@IsOptional()
|
|
95
|
+
@Type(() => Number)
|
|
96
|
+
@IsInt()
|
|
97
|
+
@Min(0)
|
|
98
|
+
idleTimeoutMs?: number;
|
|
99
|
+
|
|
100
|
+
@ApiPropertyOptional()
|
|
101
|
+
@IsOptional()
|
|
102
|
+
@Type(() => Number)
|
|
103
|
+
@IsInt()
|
|
104
|
+
@Min(0)
|
|
105
|
+
statementTimeoutMs?: number;
|
|
106
|
+
|
|
107
|
+
@ApiPropertyOptional()
|
|
108
|
+
@IsOptional()
|
|
109
|
+
@Type(() => Number)
|
|
110
|
+
@IsInt()
|
|
111
|
+
@Min(0)
|
|
112
|
+
idleInTxTimeoutMs?: number;
|
|
113
|
+
|
|
114
|
+
@ApiPropertyOptional()
|
|
115
|
+
@IsOptional()
|
|
116
|
+
@Type(() => Number)
|
|
117
|
+
@IsInt()
|
|
118
|
+
@Min(0)
|
|
119
|
+
retryAttempts?: number;
|
|
120
|
+
|
|
121
|
+
@ApiPropertyOptional()
|
|
122
|
+
@IsOptional()
|
|
123
|
+
@Type(() => Number)
|
|
124
|
+
@IsInt()
|
|
125
|
+
@Min(0)
|
|
126
|
+
retryDelayMs?: number;
|
|
127
|
+
|
|
128
|
+
@ApiPropertyOptional()
|
|
129
|
+
@IsOptional()
|
|
130
|
+
@Type(() => Boolean)
|
|
131
|
+
@IsBoolean()
|
|
132
|
+
encrypt?: boolean;
|
|
133
|
+
|
|
134
|
+
@ApiPropertyOptional()
|
|
135
|
+
@IsOptional()
|
|
136
|
+
@Type(() => Boolean)
|
|
137
|
+
@IsBoolean()
|
|
138
|
+
trustServerCertificate?: boolean;
|
|
139
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { ApiProperty } from "@nestjs/swagger";
|
|
2
|
+
import { Type } from "class-transformer";
|
|
3
|
+
import {
|
|
4
|
+
IsArray,
|
|
5
|
+
IsBoolean,
|
|
6
|
+
IsEnum,
|
|
7
|
+
IsInt,
|
|
8
|
+
IsObject,
|
|
9
|
+
IsOptional,
|
|
10
|
+
IsString,
|
|
11
|
+
ValidateNested,
|
|
12
|
+
} from "class-validator";
|
|
13
|
+
import { OrmType, SolidFieldType } from "./create-field-metadata.dto";
|
|
14
|
+
import { LegacyTableType } from "src/enums/legacy-table-type.enum";
|
|
15
|
+
|
|
16
|
+
export class DatasourceIntrospectionMappingColumnDto {
|
|
17
|
+
@ApiProperty()
|
|
18
|
+
@IsString()
|
|
19
|
+
columnName: string;
|
|
20
|
+
|
|
21
|
+
@ApiProperty()
|
|
22
|
+
@IsString()
|
|
23
|
+
fieldName: string;
|
|
24
|
+
|
|
25
|
+
@ApiProperty()
|
|
26
|
+
@IsString()
|
|
27
|
+
dataType: string;
|
|
28
|
+
|
|
29
|
+
@ApiProperty({ enum: SolidFieldType })
|
|
30
|
+
@IsEnum(SolidFieldType)
|
|
31
|
+
solidFieldType: SolidFieldType;
|
|
32
|
+
|
|
33
|
+
@ApiProperty()
|
|
34
|
+
@IsString()
|
|
35
|
+
ormType: OrmType;
|
|
36
|
+
|
|
37
|
+
@ApiProperty()
|
|
38
|
+
@IsBoolean()
|
|
39
|
+
nullable: boolean;
|
|
40
|
+
|
|
41
|
+
@ApiProperty({ required: false, nullable: true })
|
|
42
|
+
@IsOptional()
|
|
43
|
+
defaultValue?: string | null;
|
|
44
|
+
|
|
45
|
+
@ApiProperty({ required: false, nullable: true })
|
|
46
|
+
@IsOptional()
|
|
47
|
+
@IsInt()
|
|
48
|
+
characterMaximumLength?: number | null;
|
|
49
|
+
|
|
50
|
+
@ApiProperty({ required: false, nullable: true })
|
|
51
|
+
@IsOptional()
|
|
52
|
+
@IsInt()
|
|
53
|
+
numericPrecision?: number | null;
|
|
54
|
+
|
|
55
|
+
@ApiProperty({ required: false, nullable: true })
|
|
56
|
+
@IsOptional()
|
|
57
|
+
@IsInt()
|
|
58
|
+
numericScale?: number | null;
|
|
59
|
+
|
|
60
|
+
@ApiProperty({ required: false, nullable: true })
|
|
61
|
+
@IsOptional()
|
|
62
|
+
@IsInt()
|
|
63
|
+
ordinalPosition?: number | null;
|
|
64
|
+
|
|
65
|
+
@ApiProperty()
|
|
66
|
+
@IsBoolean()
|
|
67
|
+
isAutoGenerated: boolean;
|
|
68
|
+
|
|
69
|
+
@ApiProperty()
|
|
70
|
+
@IsBoolean()
|
|
71
|
+
handledBySuperclass: boolean;
|
|
72
|
+
|
|
73
|
+
@ApiProperty({ required: false, nullable: true })
|
|
74
|
+
@IsOptional()
|
|
75
|
+
@IsString()
|
|
76
|
+
superclassFieldName?: string | null;
|
|
77
|
+
|
|
78
|
+
@ApiProperty({ required: false, nullable: true })
|
|
79
|
+
@IsOptional()
|
|
80
|
+
@IsInt()
|
|
81
|
+
fieldId?: number | null;
|
|
82
|
+
|
|
83
|
+
@ApiProperty()
|
|
84
|
+
@IsBoolean()
|
|
85
|
+
include: boolean;
|
|
86
|
+
|
|
87
|
+
@ApiProperty()
|
|
88
|
+
@IsBoolean()
|
|
89
|
+
matched: boolean;
|
|
90
|
+
|
|
91
|
+
@ApiProperty()
|
|
92
|
+
@IsBoolean()
|
|
93
|
+
isPrimaryKey: boolean;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class DatasourceIntrospectionMappingDto {
|
|
97
|
+
@ApiProperty()
|
|
98
|
+
@IsBoolean()
|
|
99
|
+
mapped: boolean;
|
|
100
|
+
|
|
101
|
+
@ApiProperty({ required: false, nullable: true })
|
|
102
|
+
@IsOptional()
|
|
103
|
+
@IsInt()
|
|
104
|
+
modelId?: number | null;
|
|
105
|
+
|
|
106
|
+
@ApiProperty()
|
|
107
|
+
@IsString()
|
|
108
|
+
singularName: string;
|
|
109
|
+
|
|
110
|
+
@ApiProperty()
|
|
111
|
+
@IsString()
|
|
112
|
+
pluralName: string;
|
|
113
|
+
|
|
114
|
+
@ApiProperty()
|
|
115
|
+
@IsString()
|
|
116
|
+
displayName: string;
|
|
117
|
+
|
|
118
|
+
@ApiProperty()
|
|
119
|
+
@IsString()
|
|
120
|
+
description: string;
|
|
121
|
+
|
|
122
|
+
@ApiProperty()
|
|
123
|
+
@IsString()
|
|
124
|
+
tableName: string;
|
|
125
|
+
|
|
126
|
+
@ApiProperty({ required: false, nullable: true })
|
|
127
|
+
@IsOptional()
|
|
128
|
+
@IsString()
|
|
129
|
+
schema?: string | null;
|
|
130
|
+
|
|
131
|
+
@ApiProperty()
|
|
132
|
+
@IsString()
|
|
133
|
+
dataSource: string;
|
|
134
|
+
|
|
135
|
+
@ApiProperty()
|
|
136
|
+
@IsString()
|
|
137
|
+
dataSourceType: string;
|
|
138
|
+
|
|
139
|
+
@ApiProperty({ enum: LegacyTableType })
|
|
140
|
+
@IsEnum(LegacyTableType)
|
|
141
|
+
legacyTableType: LegacyTableType;
|
|
142
|
+
|
|
143
|
+
@ApiProperty()
|
|
144
|
+
@IsString()
|
|
145
|
+
baseClassName: string;
|
|
146
|
+
|
|
147
|
+
@ApiProperty()
|
|
148
|
+
@IsString()
|
|
149
|
+
userKeyField: string;
|
|
150
|
+
|
|
151
|
+
@ApiProperty()
|
|
152
|
+
@IsBoolean()
|
|
153
|
+
enableAuditTracking: boolean;
|
|
154
|
+
|
|
155
|
+
@ApiProperty()
|
|
156
|
+
@IsBoolean()
|
|
157
|
+
enableSoftDelete: boolean;
|
|
158
|
+
|
|
159
|
+
@ApiProperty()
|
|
160
|
+
@IsBoolean()
|
|
161
|
+
draftPublishWorkflow: boolean;
|
|
162
|
+
|
|
163
|
+
@ApiProperty()
|
|
164
|
+
@IsBoolean()
|
|
165
|
+
internationalisation: boolean;
|
|
166
|
+
|
|
167
|
+
@ApiProperty({ required: false, nullable: true })
|
|
168
|
+
@IsOptional()
|
|
169
|
+
@IsInt()
|
|
170
|
+
plannedMigrationTimestamp?: number | null;
|
|
171
|
+
|
|
172
|
+
@ApiProperty({ type: () => [DatasourceIntrospectionMappingColumnDto] })
|
|
173
|
+
@IsArray()
|
|
174
|
+
@ValidateNested({ each: true })
|
|
175
|
+
@Type(() => DatasourceIntrospectionMappingColumnDto)
|
|
176
|
+
columns: DatasourceIntrospectionMappingColumnDto[];
|
|
177
|
+
|
|
178
|
+
@ApiProperty({ required: false, type: "object" })
|
|
179
|
+
@IsOptional()
|
|
180
|
+
@IsObject()
|
|
181
|
+
reviewedModel?: Record<string, any>;
|
|
182
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -62,6 +62,7 @@ export * from './dtos/create-view-metadata.dto'
|
|
|
62
62
|
export * from './dtos/create-chatter-message.dto'
|
|
63
63
|
export * from './dtos/create-chatter-message-details.dto'
|
|
64
64
|
export * from './dtos/create-locale.dto'
|
|
65
|
+
export * from './dtos/create-datasource-management.dto'
|
|
65
66
|
export * from './dtos/fetch-roles.dto'
|
|
66
67
|
export * from './dtos/initiate-forgot-password.dto'
|
|
67
68
|
export * from './dtos/mutate-role-permissions.dto'
|
|
@@ -334,7 +335,11 @@ export * from './services/whatsapp/GupshupOtpWhatsappService'
|
|
|
334
335
|
export * from './services/setting.service'
|
|
335
336
|
export * from './services/encryption.service'
|
|
336
337
|
export * from './services/info.service'
|
|
338
|
+
export * from './services/datasource-management.service'
|
|
339
|
+
export * from './services/datasource-introspection.service'
|
|
337
340
|
export * from './controllers/info.controller'
|
|
341
|
+
export * from './controllers/datasource-management.controller'
|
|
342
|
+
export * from './controllers/datasource-introspection.controller'
|
|
338
343
|
export * from './controllers/module-metadata-explorer.controller'
|
|
339
344
|
export * from './controllers/module-package.controller'
|
|
340
345
|
export * from './services/settings/default-settings-provider.service'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DataSource } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export type DatasourceIntrospectionTableRef = {
|
|
4
|
+
tableSchema: string | null;
|
|
5
|
+
tableName: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export type DatasourceIntrospectionColumn = {
|
|
9
|
+
tableSchema: string | null;
|
|
10
|
+
tableName: string;
|
|
11
|
+
columnName: string;
|
|
12
|
+
dataType: string;
|
|
13
|
+
isAutoGenerated: boolean;
|
|
14
|
+
isNullable: boolean;
|
|
15
|
+
defaultValue: string | null;
|
|
16
|
+
characterMaximumLength: number | null;
|
|
17
|
+
numericPrecision: number | null;
|
|
18
|
+
numericScale: number | null;
|
|
19
|
+
ordinalPosition: number | null;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface DatasourceIntrospectionProvider {
|
|
23
|
+
readonly type: string;
|
|
24
|
+
supports(type: string): boolean;
|
|
25
|
+
listTables(dataSource: DataSource): Promise<DatasourceIntrospectionTableRef[]>;
|
|
26
|
+
listColumns(dataSource: DataSource): Promise<DatasourceIntrospectionColumn[]>;
|
|
27
|
+
getTableDefinition(dataSource: DataSource, table: DatasourceIntrospectionTableRef): Promise<string | null>;
|
|
28
|
+
}
|
|
@@ -5381,6 +5381,19 @@
|
|
|
5381
5381
|
"moduleUserKey": "solid-core",
|
|
5382
5382
|
"modelUserKey": "fieldMetadata"
|
|
5383
5383
|
},
|
|
5384
|
+
{
|
|
5385
|
+
"displayName": "Datasource Management",
|
|
5386
|
+
"name": "datasource-management-action",
|
|
5387
|
+
"type": "custom",
|
|
5388
|
+
"domain": "",
|
|
5389
|
+
"context": "",
|
|
5390
|
+
"customComponent": "/admin/core/solid-core/datasources",
|
|
5391
|
+
"customIsModal": true,
|
|
5392
|
+
"serverEndpoint": "",
|
|
5393
|
+
"viewUserKey": "",
|
|
5394
|
+
"moduleUserKey": "solid-core",
|
|
5395
|
+
"modelUserKey": "moduleMetadata"
|
|
5396
|
+
},
|
|
5384
5397
|
{
|
|
5385
5398
|
"displayName": "Field Metadata Tree Action",
|
|
5386
5399
|
"name": "fieldMetadata-tree-action",
|
|
@@ -6105,6 +6118,14 @@
|
|
|
6105
6118
|
"moduleUserKey": "solid-core",
|
|
6106
6119
|
"parentMenuItemUserKey": "appBuilder-menu-item"
|
|
6107
6120
|
},
|
|
6121
|
+
{
|
|
6122
|
+
"displayName": "Datasources",
|
|
6123
|
+
"name": "datasource-management-menu-item",
|
|
6124
|
+
"sequenceNumber": 4,
|
|
6125
|
+
"actionUserKey": "datasource-management-action",
|
|
6126
|
+
"moduleUserKey": "solid-core",
|
|
6127
|
+
"parentMenuItemUserKey": "appBuilder-menu-item"
|
|
6128
|
+
},
|
|
6108
6129
|
{
|
|
6109
6130
|
"displayName": "Menu Item",
|
|
6110
6131
|
"name": "menuItemMetadata-menu-item",
|
|
@@ -14737,4 +14758,4 @@
|
|
|
14737
14758
|
}
|
|
14738
14759
|
],
|
|
14739
14760
|
"savedFilters": []
|
|
14740
|
-
}
|
|
14761
|
+
}
|
|
@@ -309,7 +309,7 @@ export class AuthenticationService {
|
|
|
309
309
|
if (signUpDto.roles && signUpDto.roles.length > 0) {
|
|
310
310
|
for (let i = 0; i < signUpDto.roles.length; i++) {
|
|
311
311
|
const roleName = signUpDto.roles[i];
|
|
312
|
-
await this.roleMetadataService.
|
|
312
|
+
await this.roleMetadataService.assertRoleExistsByName(roleName);
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
315
|
user.username = signUpDto.username;
|
|
@@ -2,7 +2,13 @@ import { Injectable } from "@nestjs/common";
|
|
|
2
2
|
import { DashboardWidgetDataProvider } from "src/decorators/dashboard-widget-data-provider.decorator";
|
|
3
3
|
import { MqMessageRepository } from "src/repository/mq-message.repository";
|
|
4
4
|
import { IDashboardWidgetDataProvider, IDashboardWidgetDataProviderContext, IDashboardWidgetDataResponseEnvelope } from "src/interfaces";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
applyMqDashboardFilters,
|
|
7
|
+
buildMqDashboardBucketExpression,
|
|
8
|
+
normalizeBucket,
|
|
9
|
+
normalizeMqDashboardBucketValue,
|
|
10
|
+
toNumber,
|
|
11
|
+
} from "src/services/dashboard-providers/mq-dashboard-provider-utils";
|
|
6
12
|
|
|
7
13
|
@DashboardWidgetDataProvider()
|
|
8
14
|
@Injectable()
|
|
@@ -29,7 +35,7 @@ export class MqDashboardLatencyTrendProvider implements IDashboardWidgetDataProv
|
|
|
29
35
|
applyMqDashboardFilters(qb, ctxt.variables ?? {});
|
|
30
36
|
qb.andWhere("mqMessage.elapsedMillis IS NOT NULL");
|
|
31
37
|
|
|
32
|
-
const bucketExpr =
|
|
38
|
+
const bucketExpr = buildMqDashboardBucketExpression(qb, bucket, "mqMessage.createdAt");
|
|
33
39
|
const rows = await qb
|
|
34
40
|
.select(bucketExpr, "bucket")
|
|
35
41
|
.addSelect("AVG(mqMessage.elapsedMillis)", "value")
|
|
@@ -37,7 +43,7 @@ export class MqDashboardLatencyTrendProvider implements IDashboardWidgetDataProv
|
|
|
37
43
|
.orderBy("bucket", "ASC")
|
|
38
44
|
.getRawMany<{ bucket: string; value: string | number }>();
|
|
39
45
|
|
|
40
|
-
const categories = rows.map((r) =>
|
|
46
|
+
const categories = rows.map((r) => normalizeMqDashboardBucketValue(r.bucket));
|
|
41
47
|
const values = rows.map((r) => Number(toNumber(r.value).toFixed(2)));
|
|
42
48
|
|
|
43
49
|
return {
|
|
@@ -55,4 +61,3 @@ export class MqDashboardLatencyTrendProvider implements IDashboardWidgetDataProv
|
|
|
55
61
|
};
|
|
56
62
|
}
|
|
57
63
|
}
|
|
58
|
-
|
package/src/services/dashboard-providers/mq-dashboard-messages-over-time-provider.service.ts
CHANGED
|
@@ -2,7 +2,13 @@ import { Injectable } from "@nestjs/common";
|
|
|
2
2
|
import { DashboardWidgetDataProvider } from "src/decorators/dashboard-widget-data-provider.decorator";
|
|
3
3
|
import { MqMessageRepository } from "src/repository/mq-message.repository";
|
|
4
4
|
import { IDashboardWidgetDataProvider, IDashboardWidgetDataProviderContext, IDashboardWidgetDataResponseEnvelope } from "src/interfaces";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
applyMqDashboardFilters,
|
|
7
|
+
buildMqDashboardBucketExpression,
|
|
8
|
+
normalizeBucket,
|
|
9
|
+
normalizeMqDashboardBucketValue,
|
|
10
|
+
toNumber,
|
|
11
|
+
} from "src/services/dashboard-providers/mq-dashboard-provider-utils";
|
|
6
12
|
|
|
7
13
|
@DashboardWidgetDataProvider()
|
|
8
14
|
@Injectable()
|
|
@@ -31,7 +37,7 @@ export class MqDashboardMessagesOverTimeProvider implements IDashboardWidgetData
|
|
|
31
37
|
const qb = await this.mqMessageRepository.createSecurityRuleAwareQueryBuilder("mqMessage");
|
|
32
38
|
applyMqDashboardFilters(qb, ctxt.variables ?? {});
|
|
33
39
|
|
|
34
|
-
const bucketExpr =
|
|
40
|
+
const bucketExpr = buildMqDashboardBucketExpression(qb, bucket, "mqMessage.createdAt");
|
|
35
41
|
const rows = await qb
|
|
36
42
|
.select(bucketExpr, "bucket")
|
|
37
43
|
.addSelect("mqMessage.stage", "stage")
|
|
@@ -43,7 +49,7 @@ export class MqDashboardMessagesOverTimeProvider implements IDashboardWidgetData
|
|
|
43
49
|
|
|
44
50
|
const bucketToStageMap = new Map<string, Record<string, number>>();
|
|
45
51
|
for (const row of rows) {
|
|
46
|
-
const key =
|
|
52
|
+
const key = normalizeMqDashboardBucketValue(row.bucket);
|
|
47
53
|
const entry = bucketToStageMap.get(key) ?? {};
|
|
48
54
|
entry[row.stage] = (entry[row.stage] ?? 0) + toNumber(row.count, 0);
|
|
49
55
|
bucketToStageMap.set(key, entry);
|
|
@@ -76,4 +82,3 @@ export class MqDashboardMessagesOverTimeProvider implements IDashboardWidgetData
|
|
|
76
82
|
};
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
|
-
|
|
@@ -54,6 +54,59 @@ export function toNumber(value: any, fallback = 0): number {
|
|
|
54
54
|
return Number.isFinite(n) ? n : fallback;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
export function buildMqDashboardBucketExpression(
|
|
58
|
+
qb: SelectQueryBuilder<MqMessage>,
|
|
59
|
+
bucket: 'hour' | 'day' | 'week' | 'month',
|
|
60
|
+
columnExpr: string,
|
|
61
|
+
): string {
|
|
62
|
+
const driver = `${qb.connection.options.type ?? ''}`.toLowerCase();
|
|
63
|
+
|
|
64
|
+
switch (driver) {
|
|
65
|
+
case 'postgres':
|
|
66
|
+
case 'cockroachdb':
|
|
67
|
+
return `DATE_TRUNC('${bucket}', ${columnExpr})`;
|
|
68
|
+
case 'mysql':
|
|
69
|
+
case 'mariadb':
|
|
70
|
+
switch (bucket) {
|
|
71
|
+
case 'hour':
|
|
72
|
+
return `DATE_FORMAT(${columnExpr}, '%Y-%m-%d %H:00:00')`;
|
|
73
|
+
case 'day':
|
|
74
|
+
return `DATE_FORMAT(${columnExpr}, '%Y-%m-%d 00:00:00')`;
|
|
75
|
+
case 'week':
|
|
76
|
+
return `STR_TO_DATE(DATE_FORMAT(${columnExpr}, '%x-%v-1'), '%x-%v-%w')`;
|
|
77
|
+
case 'month':
|
|
78
|
+
return `DATE_FORMAT(${columnExpr}, '%Y-%m-01 00:00:00')`;
|
|
79
|
+
default:
|
|
80
|
+
throw new Error(`Unsupported bucket ${bucket} for driver ${driver}`);
|
|
81
|
+
}
|
|
82
|
+
case 'mssql':
|
|
83
|
+
case 'sqlserver':
|
|
84
|
+
switch (bucket) {
|
|
85
|
+
case 'hour':
|
|
86
|
+
return `DATEADD(hour, DATEDIFF(hour, 0, ${columnExpr}), 0)`;
|
|
87
|
+
case 'day':
|
|
88
|
+
return `DATEADD(day, DATEDIFF(day, 0, ${columnExpr}), 0)`;
|
|
89
|
+
case 'week':
|
|
90
|
+
return `DATEADD(week, DATEDIFF(week, 0, ${columnExpr}), 0)`;
|
|
91
|
+
case 'month':
|
|
92
|
+
return `DATEFROMPARTS(YEAR(${columnExpr}), MONTH(${columnExpr}), 1)`;
|
|
93
|
+
default:
|
|
94
|
+
throw new Error(`Unsupported bucket ${bucket} for driver ${driver}`);
|
|
95
|
+
}
|
|
96
|
+
default:
|
|
97
|
+
throw new Error(`Unsupported driver ${driver} for mq dashboard bucket expressions.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function normalizeMqDashboardBucketValue(value: any): string {
|
|
102
|
+
if (!value) return '';
|
|
103
|
+
const parsed = value instanceof Date ? value : new Date(value);
|
|
104
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
105
|
+
return `${value}`;
|
|
106
|
+
}
|
|
107
|
+
return parsed.toISOString();
|
|
108
|
+
}
|
|
109
|
+
|
|
57
110
|
|
|
58
111
|
function applyDateFilter(qb: SelectQueryBuilder<MqMessage>, dateVariable: any): void {
|
|
59
112
|
const range = resolveDateRange(dateVariable);
|
|
@@ -88,6 +141,35 @@ function applyStringOrArrayFilter(
|
|
|
88
141
|
qb.andWhere(`${qualifiedColumn} IN (:...${paramKey})`, { [paramKey]: values });
|
|
89
142
|
}
|
|
90
143
|
|
|
144
|
+
export function applyCaseInsensitiveContainsFilter<T>(
|
|
145
|
+
qb: SelectQueryBuilder<T>,
|
|
146
|
+
qualifiedColumn: string,
|
|
147
|
+
query: string | undefined,
|
|
148
|
+
paramKey: string,
|
|
149
|
+
) {
|
|
150
|
+
if (!query) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const driver = `${qb.connection.options.type ?? ''}`.toLowerCase();
|
|
155
|
+
const value = `%${query}%`;
|
|
156
|
+
|
|
157
|
+
switch (driver) {
|
|
158
|
+
case 'postgres':
|
|
159
|
+
case 'cockroachdb':
|
|
160
|
+
qb.andWhere(`${qualifiedColumn} ILIKE :${paramKey}`, { [paramKey]: value });
|
|
161
|
+
return;
|
|
162
|
+
case 'mysql':
|
|
163
|
+
case 'mariadb':
|
|
164
|
+
case 'mssql':
|
|
165
|
+
case 'sqlserver':
|
|
166
|
+
qb.andWhere(`LOWER(${qualifiedColumn}) LIKE LOWER(:${paramKey})`, { [paramKey]: value });
|
|
167
|
+
return;
|
|
168
|
+
default:
|
|
169
|
+
qb.andWhere(`${qualifiedColumn} LIKE :${paramKey}`, { [paramKey]: value });
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
91
173
|
function resolveDateRange(dateVariable: any): { from?: Date; to?: Date } {
|
|
92
174
|
if (!dateVariable) return {};
|
|
93
175
|
|