@solidxai/core 0.1.11-beta.1 → 0.1.11-beta.4

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.
Files changed (136) hide show
  1. package/.claude/settings.local.json +16 -0
  2. package/CLAUDE.md +26 -0
  3. package/dist/controllers/datasource-introspection.controller.d.ts +38 -1
  4. package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -1
  5. package/dist/controllers/datasource-introspection.controller.js +38 -0
  6. package/dist/controllers/datasource-introspection.controller.js.map +1 -1
  7. package/dist/controllers/service.controller.d.ts +1 -0
  8. package/dist/controllers/service.controller.d.ts.map +1 -1
  9. package/dist/controllers/service.controller.js +2 -2
  10. package/dist/controllers/service.controller.js.map +1 -1
  11. package/dist/dtos/datasource-introspection-mapping.dto.d.ts +4 -0
  12. package/dist/dtos/datasource-introspection-mapping.dto.d.ts.map +1 -1
  13. package/dist/dtos/datasource-introspection-mapping.dto.js +18 -2
  14. package/dist/dtos/datasource-introspection-mapping.dto.js.map +1 -1
  15. package/dist/entities/{legacy-common-with-id.entity.d.ts → legacy-common-with-generated-id.entity.d.ts} +2 -2
  16. package/dist/entities/legacy-common-with-generated-id.entity.d.ts.map +1 -0
  17. package/dist/entities/{legacy-common-with-id.entity.js → legacy-common-with-generated-id.entity.js} +4 -4
  18. package/dist/entities/legacy-common-with-generated-id.entity.js.map +1 -0
  19. package/dist/entities/{legacy-common.entity.d.ts → legacy-common.entity-with-existing-id.entity.d.ts} +1 -1
  20. package/dist/entities/legacy-common.entity-with-existing-id.entity.d.ts.map +1 -0
  21. package/dist/entities/{legacy-common.entity.js → legacy-common.entity-with-existing-id.entity.js} +1 -1
  22. package/dist/entities/legacy-common.entity-with-existing-id.entity.js.map +1 -0
  23. package/dist/helpers/field-crud-managers/IntFieldCrudManager.d.ts.map +1 -1
  24. package/dist/helpers/field-crud-managers/IntFieldCrudManager.js +4 -1
  25. package/dist/helpers/field-crud-managers/IntFieldCrudManager.js.map +1 -1
  26. package/dist/helpers/model-metadata-helper.service.js +3 -3
  27. package/dist/helpers/model-metadata-helper.service.js.map +1 -1
  28. package/dist/helpers/solid-registry.d.ts +2 -1
  29. package/dist/helpers/solid-registry.d.ts.map +1 -1
  30. package/dist/helpers/solid-registry.js.map +1 -1
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/interfaces/datasource-introspection-provider.interface.d.ts +1 -0
  36. package/dist/interfaces/datasource-introspection-provider.interface.d.ts.map +1 -1
  37. package/dist/interfaces/datasource-introspection-provider.interface.js.map +1 -1
  38. package/dist/seeders/module-metadata-seeder.service.d.ts +5 -1
  39. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  40. package/dist/seeders/module-metadata-seeder.service.js +61 -3
  41. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  42. package/dist/seeders/seed-data/solid-core-metadata.json +19 -3
  43. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
  44. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +6 -5
  45. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
  46. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts.map +1 -1
  47. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js +12 -0
  48. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js.map +1 -1
  49. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts.map +1 -1
  50. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js +2 -0
  51. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js.map +1 -1
  52. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts.map +1 -1
  53. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js +28 -15
  54. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js.map +1 -1
  55. package/dist/services/datasource-introspection.service.d.ts +52 -2
  56. package/dist/services/datasource-introspection.service.d.ts.map +1 -1
  57. package/dist/services/datasource-introspection.service.js +534 -160
  58. package/dist/services/datasource-introspection.service.js.map +1 -1
  59. package/dist/services/locale.service.d.ts +14 -0
  60. package/dist/services/locale.service.d.ts.map +1 -1
  61. package/dist/services/locale.service.js +83 -0
  62. package/dist/services/locale.service.js.map +1 -1
  63. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +10 -10
  64. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
  65. package/dist/services/role-metadata.service.d.ts +1 -0
  66. package/dist/services/role-metadata.service.d.ts.map +1 -1
  67. package/dist/services/role-metadata.service.js +23 -2
  68. package/dist/services/role-metadata.service.js.map +1 -1
  69. package/dist/services/view-metadata.service.d.ts.map +1 -1
  70. package/dist/services/view-metadata.service.js +4 -7
  71. package/dist/services/view-metadata.service.js.map +1 -1
  72. package/dist/subscribers/audit.subscriber.d.ts +2 -0
  73. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  74. package/dist/subscribers/audit.subscriber.js +25 -6
  75. package/dist/subscribers/audit.subscriber.js.map +1 -1
  76. package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
  77. package/dist/subscribers/computed-entity-field.subscriber.js +1 -0
  78. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  79. package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
  80. package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
  81. package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
  82. package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
  83. package/package.json +1 -1
  84. package/src/controllers/datasource-introspection.controller.ts +27 -1
  85. package/src/controllers/service.controller.ts +3 -2
  86. package/src/dtos/datasource-introspection-mapping.dto.ts +10 -0
  87. package/src/entities/{legacy-common-with-id.entity.ts → legacy-common-with-generated-id.entity.ts} +1 -1
  88. package/src/helpers/field-crud-managers/IntFieldCrudManager.ts +4 -1
  89. package/src/helpers/model-metadata-helper.service.ts +1 -1
  90. package/src/helpers/solid-registry.ts +7 -1
  91. package/src/index.ts +2 -2
  92. package/src/interfaces/datasource-introspection-provider.interface.ts +1 -0
  93. package/src/seeders/module-metadata-seeder.service.ts +72 -2
  94. package/src/seeders/seed-data/solid-core-metadata.json +19 -3
  95. package/src/services/1.js +6 -0
  96. package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +10 -5
  97. package/src/services/datasource-introspection/mssql-datasource-introspection-provider.service.ts +12 -0
  98. package/src/services/datasource-introspection/mysql-datasource-introspection-provider.service.ts +2 -0
  99. package/src/services/datasource-introspection/postgres-datasource-introspection-provider.service.ts +28 -15
  100. package/src/services/datasource-introspection.service.ts +626 -136
  101. package/src/services/locale.service.ts +111 -3
  102. package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +2 -2
  103. package/src/services/role-metadata.service.ts +26 -2
  104. package/src/services/view-metadata.service.ts +4 -8
  105. package/src/subscribers/audit.subscriber.ts +34 -14
  106. package/src/subscribers/computed-entity-field.subscriber.ts +1 -0
  107. package/src/subscribers/created-by-updated-by.subscriber.ts +3 -0
  108. package/src/subscribers/field-metadata.subscriber.ts +3 -0
  109. package/dist/entities/legacy-common-with-id.entity.d.ts.map +0 -1
  110. package/dist/entities/legacy-common-with-id.entity.js.map +0 -1
  111. package/dist/entities/legacy-common.entity.d.ts.map +0 -1
  112. package/dist/entities/legacy-common.entity.js.map +0 -1
  113. package/dist-tests/api/authenticate.spec.js +0 -119
  114. package/dist-tests/api/authenticate.spec.js.map +0 -1
  115. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +0 -97
  116. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +0 -1
  117. package/dist-tests/api/ping.spec.js +0 -21
  118. package/dist-tests/api/ping.spec.js.map +0 -1
  119. package/dist-tests/helpers/auth.js +0 -41
  120. package/dist-tests/helpers/auth.js.map +0 -1
  121. package/dist-tests/helpers/env.js +0 -11
  122. package/dist-tests/helpers/env.js.map +0 -1
  123. package/docs/agent-hub-grooming.md +0 -301
  124. package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +0 -438
  125. package/docs/dashboards/dashboard-curl-smoke-tests.txt +0 -146
  126. package/docs/dashboards/delete-legacy-dashboard-metadata.sql +0 -172
  127. package/docs/datasource-introspection-ddl-analysis.md +0 -326
  128. package/docs/datasource-introspection-implementation-plan.md +0 -306
  129. package/docs/grouping-enhancements.md +0 -89
  130. package/docs/java-spring/README.md +0 -3
  131. package/docs/java-spring/solid-core-module-deep-dive-report.md +0 -1317
  132. package/docs/module-package-import-handoff.md +0 -691
  133. package/docs/seed-changes.md +0 -65
  134. package/docs/test-data-workflow.md +0 -200
  135. package/docs/type-declaration-import-issue.md +0 -24
  136. /package/src/entities/{legacy-common.entity.ts → legacy-common.entity-with-existing-id.entity.ts} +0 -0
package/src/index.ts CHANGED
@@ -119,8 +119,8 @@ export * from './dtos/update-dashboard-user-layout.dto'
119
119
 
120
120
  export * from './entities/action-metadata.entity'
121
121
  export * from './entities/common.entity'
122
- export * from './entities/legacy-common.entity'
123
- export * from './entities/legacy-common-with-id.entity'
122
+ export * from './entities/legacy-common.entity-with-existing-id.entity'
123
+ export * from './entities/legacy-common-with-generated-id.entity'
124
124
  export * from './entities/email-attachment.entity'
125
125
  export * from './entities/email-template.entity'
126
126
  export * from './entities/field-metadata.entity'
@@ -11,6 +11,7 @@ export type DatasourceIntrospectionColumn = {
11
11
  columnName: string;
12
12
  dataType: string;
13
13
  isAutoGenerated: boolean;
14
+ isPrimaryKey: boolean;
14
15
  isNullable: boolean;
15
16
  defaultValue: string | null;
16
17
  characterMaximumLength: number | null;
@@ -39,12 +39,14 @@ import { SignUpDto } from '../dtos/sign-up.dto';
39
39
  import { ADMIN_ROLE_NAME, CreateRoleMetadataDto } from 'src/dtos/create-role-metadata.dto';
40
40
  import { CreateSavedFiltersDto } from 'src/dtos/create-saved-filters.dto';
41
41
  import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto';
42
+ import { CreateLocaleDto } from 'src/dtos/create-locale.dto';
42
43
  import { PermissionMetadataRepository } from 'src/repository/permission-metadata.repository';
43
44
  import { SavedFiltersRepository } from 'src/repository/saved-filters.repository';
44
45
  import { ScheduledJobRepository } from 'src/repository/scheduled-job.repository';
45
46
  import { SettingRepository } from 'src/repository/setting.repository';
46
47
  import { CreateModelSequenceDto } from 'src/dtos/create-model-sequence.dto';
47
48
  import { ModelSequenceRepository } from 'src/repository/model-sequence.repository';
49
+ import { LocaleRepository } from 'src/repository/locale.repository';
48
50
  import { ModelSequence } from 'src/entities/model-sequence.entity';
49
51
  import { SavedFilters } from 'src/entities/saved-filters.entity';
50
52
  import { ScheduledJob } from 'src/entities/scheduled-job.entity';
@@ -116,6 +118,7 @@ export class ModuleMetadataSeederService {
116
118
  readonly savedFiltersRepo: SavedFiltersRepository,
117
119
  readonly dataSource: DataSource,
118
120
  readonly modelSequenceRepo: ModelSequenceRepository,
121
+ readonly localeRepo: LocaleRepository,
119
122
  ) { }
120
123
 
121
124
  async seed(conf?: any) {
@@ -194,6 +197,11 @@ export class ModuleMetadataSeederService {
194
197
  const moduleModelFieldCounts = await this.timeOperation('seed-module-model-fields', () => this.seedModuleModelFields(moduleMetadata), { moduleName: moduleMetadata.name, component: 'module-model-fields' });
195
198
  console.log(`${this.formatSeedResult(moduleMetadata.name, 'Module/Model/Fields', moduleModelFieldCounts)}`);
196
199
 
200
+ currentStep = 'seedLocales';
201
+ this.logger.log(`Seeding Locales`);
202
+ const localeCounts = await this.seedLocales(overallMetadata);
203
+ console.log(`${this.formatSeedResult(moduleMetadata.name, 'Locales', localeCounts)}`);
204
+
197
205
  currentStep = 'seedPermissions';
198
206
  this.logger.log(`Seeding Permissions`);
199
207
  const permissionCounts = await this.timeOperation('seed-permissions', () => this.seedPermissions(overallMetadata), { moduleName: moduleMetadata.name, component: 'permissions' });
@@ -466,6 +474,22 @@ export class ModuleMetadataSeederService {
466
474
  return { pruned, upserted: listOfValues.length };
467
475
  }
468
476
 
477
+ private async seedLocales(overallMetadata: any): Promise<{ pruned: number; upserted: number }> {
478
+ this.logger.debug(`[Start] Processing locales`);
479
+ const locales = this.getSeedArray<CreateLocaleDto>(overallMetadata?.locales);
480
+ const existingLocales = await this.localeRepo.find();
481
+
482
+ if (existingLocales.length > 0) {
483
+ this.solidRegistry.registerlocales(existingLocales);
484
+ this.logger.debug(`[End] Skipping locale seed because locales already exist`);
485
+ return { pruned: 0, upserted: 0 };
486
+ }
487
+
488
+ await this.handleSeedLocales(locales);
489
+ this.logger.debug(`[End] Processing locales`);
490
+ return { pruned: 0, upserted: locales.length };
491
+ }
492
+
469
493
  private async setupDefaultRolesWithPermissions() {
470
494
  this.logger.debug(`About to add all permissions to the Admin role`);
471
495
  await this.timeOperation('role-add-all-permissions', () => this.roleService.addAllPermissionsToRole(ADMIN_ROLE_NAME), {
@@ -592,11 +616,15 @@ export class ModuleMetadataSeederService {
592
616
  // OK
593
617
  private async seedRoles(overallMetadata: any): Promise<{ pruned: number; upserted: number }> {
594
618
  const roles = this.getSeedArray<CreateRoleMetadataDto>(overallMetadata?.roles);
595
- // While creating roles we are only passing the role name to be used.
619
+ // Preserve module linkage metadata so RoleMetadata.module is populated from the defining module.
596
620
  await this.timeOperation('roles-create-if-not-exists', () => this.roleService.createRolesIfNotExists(
597
621
  roles
598
622
  .filter((role) => role?.name)
599
- .map((role) => ({ name: role.name } as any)),
623
+ .map((role) => ({
624
+ name: role.name,
625
+ moduleId: role.moduleId,
626
+ moduleUserKey: role.moduleUserKey ?? overallMetadata?.moduleMetadata?.name,
627
+ } as CreateRoleMetadataDto)),
600
628
  ), {
601
629
  moduleName: overallMetadata?.moduleMetadata?.name,
602
630
  component: 'roles',
@@ -1872,6 +1900,48 @@ export class ModuleMetadataSeederService {
1872
1900
  }
1873
1901
  }
1874
1902
 
1903
+ private async handleSeedLocales(localesDto: CreateLocaleDto[]) {
1904
+ if (!localesDto || localesDto.length === 0) {
1905
+ this.logger.debug(`No locales found to seed`);
1906
+ return;
1907
+ }
1908
+
1909
+ for (const dto of localesDto) {
1910
+ if (dto.isDefault) {
1911
+ const existingDefaultLocales = await this.localeRepo.find({
1912
+ where: {
1913
+ isDefault: true,
1914
+ } as any,
1915
+ });
1916
+
1917
+ for (const locale of existingDefaultLocales) {
1918
+ if (locale.locale !== dto.locale) {
1919
+ await this.localeRepo.save({
1920
+ ...locale,
1921
+ isDefault: false,
1922
+ });
1923
+ }
1924
+ }
1925
+ }
1926
+
1927
+ const existingLocale = await this.localeRepo.findOne({
1928
+ where: {
1929
+ locale: dto.locale,
1930
+ } as any,
1931
+ });
1932
+
1933
+ await this.localeRepo.save(
1934
+ this.localeRepo.create({
1935
+ ...existingLocale,
1936
+ ...dto,
1937
+ })
1938
+ );
1939
+ }
1940
+
1941
+ const locales = await this.localeRepo.find();
1942
+ this.solidRegistry.registerlocales(locales);
1943
+ }
1944
+
1875
1945
  private validateSavedFilterQueryJsonWrapper(dto: CreateSavedFiltersDto): void {
1876
1946
  const filterName = dto?.name ?? '<unnamed>';
1877
1947
  const filterQueryJson = dto?.filterQueryJson;
@@ -1077,15 +1077,24 @@
1077
1077
  {
1078
1078
  "name": "type",
1079
1079
  "displayName": "Type",
1080
- "type": "shortText",
1080
+ "type": "selectionStatic",
1081
1081
  "ormType": "varchar",
1082
+ "length": 256,
1082
1083
  "required": true,
1083
1084
  "unique": false,
1084
1085
  "index": true,
1085
1086
  "private": false,
1086
1087
  "encrypt": false,
1087
1088
  "columnName": "type",
1088
- "isSystem": true
1089
+ "isSystem": true,
1090
+ "selectionValueType": "string",
1091
+ "selectionStaticValues": [
1092
+ "list:List",
1093
+ "form:Form",
1094
+ "tree:Tree",
1095
+ "kanban:Kanban",
1096
+ "card:Card"
1097
+ ]
1089
1098
  },
1090
1099
  {
1091
1100
  "name": "context",
@@ -1584,7 +1593,7 @@
1584
1593
  "name": "roles",
1585
1594
  "displayName": "Roles",
1586
1595
  "type": "relation",
1587
- "required": true,
1596
+ "required": false,
1588
1597
  "unique": false,
1589
1598
  "index": true,
1590
1599
  "private": false,
@@ -5244,6 +5253,13 @@
5244
5253
  }
5245
5254
  ]
5246
5255
  },
5256
+ "locales": [
5257
+ {
5258
+ "locale": "en",
5259
+ "displayName": "English",
5260
+ "isDefault": true
5261
+ }
5262
+ ],
5247
5263
  "permissions": [
5248
5264
  "mcp:invoke",
5249
5265
  "agent:invoke",
@@ -0,0 +1,6 @@
1
+ 1. Do i need to create a storeStreams method for aws service too?
2
+ - Handle later
3
+ 2. queues handling -> if queues is enabled by default, i.e triggerExport(exportTransactionEntity.id).
4
+ - startExport should either return the data or return the transaction id
5
+ 3. How to handle scenarios wherein, nested related exist.(do i need to only get the userkey)
6
+ - show the userKey
@@ -45,7 +45,12 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
45
45
  }
46
46
  }
47
47
 
48
- const uniqueCode = await this.generateUniqueExternalId(resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
48
+ // Use the originating transaction's EntityManager so the uniqueness check runs on the
49
+ // active connection. Falls back to the injected manager only when no event context is
50
+ // available (e.g. direct invocation outside a TypeORM lifecycle event).
51
+ const manager = eventContext?.manager ?? this.entityManager;
52
+
53
+ const uniqueCode = await this.generateUniqueExternalId(manager, resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
49
54
  const finalExternalId = resolvedPrefix ? `${resolvedPrefix}-${uniqueCode}` : uniqueCode;
50
55
 
51
56
  triggerEntity[computedFieldMetadata.fieldName] = finalExternalId;
@@ -60,8 +65,8 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
60
65
  return result;
61
66
  }
62
67
 
63
- private async isExternalIdUnique(externalId: string, fieldName: string, entityName: string): Promise<boolean> {
64
- const count = await this.entityManager.count(entityName as any,
68
+ private async isExternalIdUnique(manager: EntityManager, externalId: string, fieldName: string, entityName: string): Promise<boolean> {
69
+ const count = await manager.count(entityName as any,
65
70
  {
66
71
  where: { [fieldName]: externalId },
67
72
  }
@@ -69,7 +74,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
69
74
  return count === 0;
70
75
  }
71
76
 
72
- private async generateUniqueExternalId(resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {
77
+ private async generateUniqueExternalId(manager: EntityManager, resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {
73
78
  const maxAttempts = 10;
74
79
 
75
80
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -78,7 +83,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
78
83
 
79
84
  const fullId = resolvedPrefix ? `${resolvedPrefix}-${newId}` : newId;
80
85
 
81
- const isUnique = await this.isExternalIdUnique(fullId, fieldName, entityName);
86
+ const isUnique = await this.isExternalIdUnique(manager, fullId, fieldName, entityName);
82
87
 
83
88
  if (isUnique) {
84
89
  return newId;
@@ -39,6 +39,7 @@ export class MssqlDatasourceIntrospectionProviderService implements DatasourceIn
39
39
  c.name AS columnName,
40
40
  ty.name AS dataType,
41
41
  c.is_identity AS isAutoGenerated,
42
+ CASE WHEN pk.column_id IS NOT NULL THEN 1 ELSE 0 END AS isPrimaryKey,
42
43
  CASE WHEN c.is_nullable = 1 THEN 'YES' ELSE 'NO' END AS isNullable,
43
44
  dc.definition AS defaultValue,
44
45
  CASE
@@ -52,6 +53,16 @@ export class MssqlDatasourceIntrospectionProviderService implements DatasourceIn
52
53
  INNER JOIN sys.columns c ON c.object_id = t.object_id
53
54
  INNER JOIN sys.types ty ON ty.user_type_id = c.user_type_id
54
55
  LEFT JOIN sys.default_constraints dc ON dc.object_id = c.default_object_id
56
+ LEFT JOIN (
57
+ SELECT ic.object_id, ic.column_id
58
+ FROM sys.index_columns ic
59
+ INNER JOIN sys.key_constraints kc
60
+ ON kc.parent_object_id = ic.object_id
61
+ AND kc.unique_index_id = ic.index_id
62
+ WHERE kc.type = 'PK'
63
+ ) pk
64
+ ON pk.object_id = c.object_id
65
+ AND pk.column_id = c.column_id
55
66
  WHERE schema_name(t.schema_id) NOT IN ('sys', 'INFORMATION_SCHEMA')
56
67
  ORDER BY schema_name(t.schema_id), t.name, c.column_id
57
68
  `);
@@ -62,6 +73,7 @@ export class MssqlDatasourceIntrospectionProviderService implements DatasourceIn
62
73
  columnName: row.columnName,
63
74
  dataType: row.dataType,
64
75
  isAutoGenerated: Boolean(row.isAutoGenerated),
76
+ isPrimaryKey: Boolean(row.isPrimaryKey),
65
77
  isNullable: String(row.isNullable).toUpperCase() === "YES",
66
78
  defaultValue: row.defaultValue ?? null,
67
79
  characterMaximumLength: this.toNumberOrNull(row.characterMaximumLength),
@@ -39,6 +39,7 @@ export class MysqlDatasourceIntrospectionProviderService implements DatasourceIn
39
39
  COLUMN_NAME AS columnName,
40
40
  DATA_TYPE AS dataType,
41
41
  EXTRA AS extra,
42
+ COLUMN_KEY AS columnKey,
42
43
  IS_NULLABLE AS isNullable,
43
44
  COLUMN_DEFAULT AS defaultValue,
44
45
  CHARACTER_MAXIMUM_LENGTH AS characterMaximumLength,
@@ -56,6 +57,7 @@ export class MysqlDatasourceIntrospectionProviderService implements DatasourceIn
56
57
  columnName: row.columnName,
57
58
  dataType: row.dataType,
58
59
  isAutoGenerated: String(row.extra ?? "").toLowerCase().includes("auto_increment"),
60
+ isPrimaryKey: String(row.columnKey ?? "").toUpperCase() === "PRI",
59
61
  isNullable: String(row.isNullable).toUpperCase() === "YES",
60
62
  defaultValue: row.defaultValue ?? null,
61
63
  characterMaximumLength: this.toNumberOrNull(row.characterMaximumLength),
@@ -34,24 +34,36 @@ export class PostgresDatasourceIntrospectionProviderService implements Datasourc
34
34
  async listColumns(dataSource: DataSource): Promise<DatasourceIntrospectionColumn[]> {
35
35
  const rows = await dataSource.query(`
36
36
  SELECT
37
- TABLE_SCHEMA AS "tableSchema",
38
- TABLE_NAME AS "tableName",
39
- COLUMN_NAME AS "columnName",
40
- DATA_TYPE AS "dataType",
37
+ c.TABLE_SCHEMA AS "tableSchema",
38
+ c.TABLE_NAME AS "tableName",
39
+ c.COLUMN_NAME AS "columnName",
40
+ c.DATA_TYPE AS "dataType",
41
41
  CASE
42
- WHEN is_identity = 'YES' THEN true
43
- WHEN COLUMN_DEFAULT LIKE 'nextval(%' THEN true
42
+ WHEN c.is_identity = 'YES' THEN true
43
+ WHEN c.COLUMN_DEFAULT LIKE 'nextval(%' THEN true
44
44
  ELSE false
45
45
  END AS "isAutoGenerated",
46
- IS_NULLABLE AS "isNullable",
47
- COLUMN_DEFAULT AS "defaultValue",
48
- CHARACTER_MAXIMUM_LENGTH AS "characterMaximumLength",
49
- NUMERIC_PRECISION AS "numericPrecision",
50
- NUMERIC_SCALE AS "numericScale",
51
- ORDINAL_POSITION AS "ordinalPosition"
52
- FROM INFORMATION_SCHEMA.COLUMNS
53
- WHERE TABLE_SCHEMA NOT IN ('pg_catalog', 'information_schema')
54
- ORDER BY TABLE_SCHEMA, TABLE_NAME, ORDINAL_POSITION
46
+ EXISTS (
47
+ SELECT 1
48
+ FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
49
+ INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
50
+ ON kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
51
+ AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
52
+ AND kcu.TABLE_NAME = tc.TABLE_NAME
53
+ WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
54
+ AND tc.TABLE_SCHEMA = c.TABLE_SCHEMA
55
+ AND tc.TABLE_NAME = c.TABLE_NAME
56
+ AND kcu.COLUMN_NAME = c.COLUMN_NAME
57
+ ) AS "isPrimaryKey",
58
+ c.IS_NULLABLE AS "isNullable",
59
+ c.COLUMN_DEFAULT AS "defaultValue",
60
+ c.CHARACTER_MAXIMUM_LENGTH AS "characterMaximumLength",
61
+ c.NUMERIC_PRECISION AS "numericPrecision",
62
+ c.NUMERIC_SCALE AS "numericScale",
63
+ c.ORDINAL_POSITION AS "ordinalPosition"
64
+ FROM INFORMATION_SCHEMA.COLUMNS c
65
+ WHERE c.TABLE_SCHEMA NOT IN ('pg_catalog', 'information_schema')
66
+ ORDER BY c.TABLE_SCHEMA, c.TABLE_NAME, c.ORDINAL_POSITION
55
67
  `);
56
68
 
57
69
  return rows.map((row: any) => ({
@@ -60,6 +72,7 @@ export class PostgresDatasourceIntrospectionProviderService implements Datasourc
60
72
  columnName: row.columnName,
61
73
  dataType: row.dataType,
62
74
  isAutoGenerated: Boolean(row.isAutoGenerated),
75
+ isPrimaryKey: Boolean(row.isPrimaryKey),
63
76
  isNullable: String(row.isNullable).toUpperCase() === "YES",
64
77
  defaultValue: row.defaultValue ?? null,
65
78
  characterMaximumLength: this.toNumberOrNull(row.characterMaximumLength),