@solidxai/core 0.1.11-beta.2 → 0.1.11-beta.5

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 (145) hide show
  1. package/dist/commands/migrate-removed-fields.command.d.ts +19 -0
  2. package/dist/commands/migrate-removed-fields.command.d.ts.map +1 -0
  3. package/dist/commands/migrate-removed-fields.command.js +77 -0
  4. package/dist/commands/migrate-removed-fields.command.js.map +1 -0
  5. package/dist/controllers/datasource-introspection.controller.d.ts +38 -1
  6. package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -1
  7. package/dist/controllers/datasource-introspection.controller.js +38 -0
  8. package/dist/controllers/datasource-introspection.controller.js.map +1 -1
  9. package/dist/dtos/datasource-introspection-mapping.dto.d.ts +5 -0
  10. package/dist/dtos/datasource-introspection-mapping.dto.d.ts.map +1 -1
  11. package/dist/dtos/datasource-introspection-mapping.dto.js +24 -2
  12. package/dist/dtos/datasource-introspection-mapping.dto.js.map +1 -1
  13. package/dist/entities/{legacy-common-with-id.entity.d.ts → legacy-common-with-generated-id.entity.d.ts} +2 -2
  14. package/dist/entities/legacy-common-with-generated-id.entity.d.ts.map +1 -0
  15. package/dist/entities/{legacy-common-with-id.entity.js → legacy-common-with-generated-id.entity.js} +4 -4
  16. package/dist/entities/legacy-common-with-generated-id.entity.js.map +1 -0
  17. package/dist/entities/{legacy-common.entity.d.ts → legacy-common.entity-with-existing-id.entity.d.ts} +1 -1
  18. package/dist/entities/legacy-common.entity-with-existing-id.entity.d.ts.map +1 -0
  19. package/dist/entities/{legacy-common.entity.js → legacy-common.entity-with-existing-id.entity.js} +1 -1
  20. package/dist/entities/legacy-common.entity-with-existing-id.entity.js.map +1 -0
  21. package/dist/helpers/command.service.d.ts +2 -0
  22. package/dist/helpers/command.service.d.ts.map +1 -1
  23. package/dist/helpers/command.service.js +6 -2
  24. package/dist/helpers/command.service.js.map +1 -1
  25. package/dist/helpers/model-metadata-helper.service.js +3 -3
  26. package/dist/helpers/model-metadata-helper.service.js.map +1 -1
  27. package/dist/helpers/nodemon-heartbeat.d.ts +5 -0
  28. package/dist/helpers/nodemon-heartbeat.d.ts.map +1 -0
  29. package/dist/helpers/nodemon-heartbeat.js +67 -0
  30. package/dist/helpers/nodemon-heartbeat.js.map +1 -0
  31. package/dist/index.d.ts +3 -2
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +3 -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 +7 -1
  39. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  40. package/dist/seeders/module-metadata-seeder.service.js +101 -1
  41. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  42. package/dist/seeders/seed-data/solid-core-metadata.json +121 -34
  43. package/dist/services/api-key.service.d.ts.map +1 -1
  44. package/dist/services/api-key.service.js.map +1 -1
  45. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts +4 -0
  46. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts.map +1 -1
  47. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js +18 -1
  48. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js.map +1 -1
  49. package/dist/services/crud.service.d.ts +1 -0
  50. package/dist/services/crud.service.d.ts.map +1 -1
  51. package/dist/services/crud.service.js +27 -0
  52. package/dist/services/crud.service.js.map +1 -1
  53. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts.map +1 -1
  54. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js +12 -0
  55. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js.map +1 -1
  56. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts.map +1 -1
  57. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js +2 -0
  58. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js.map +1 -1
  59. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts.map +1 -1
  60. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js +28 -15
  61. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js.map +1 -1
  62. package/dist/services/datasource-introspection.service.d.ts +53 -2
  63. package/dist/services/datasource-introspection.service.d.ts.map +1 -1
  64. package/dist/services/datasource-introspection.service.js +559 -174
  65. package/dist/services/datasource-introspection.service.js.map +1 -1
  66. package/dist/services/import-transaction.service.d.ts.map +1 -1
  67. package/dist/services/import-transaction.service.js +3 -0
  68. package/dist/services/import-transaction.service.js.map +1 -1
  69. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +10 -10
  70. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
  71. package/dist/services/model-metadata.service.d.ts +1 -0
  72. package/dist/services/model-metadata.service.d.ts.map +1 -1
  73. package/dist/services/model-metadata.service.js +28 -0
  74. package/dist/services/model-metadata.service.js.map +1 -1
  75. package/dist/services/module-metadata.service.d.ts.map +1 -1
  76. package/dist/services/module-metadata.service.js +27 -0
  77. package/dist/services/module-metadata.service.js.map +1 -1
  78. package/dist/services/removed-field-migration.service.d.ts +30 -0
  79. package/dist/services/removed-field-migration.service.d.ts.map +1 -0
  80. package/dist/services/removed-field-migration.service.js +319 -0
  81. package/dist/services/removed-field-migration.service.js.map +1 -0
  82. package/dist/solid-core.module.d.ts.map +1 -1
  83. package/dist/solid-core.module.js +4 -0
  84. package/dist/solid-core.module.js.map +1 -1
  85. package/dist/subscribers/audit.subscriber.d.ts +4 -1
  86. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  87. package/dist/subscribers/audit.subscriber.js +54 -6
  88. package/dist/subscribers/audit.subscriber.js.map +1 -1
  89. package/dist-tests/api/authenticate.spec.js +119 -0
  90. package/dist-tests/api/authenticate.spec.js.map +1 -0
  91. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  92. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  93. package/dist-tests/api/ping.spec.js +21 -0
  94. package/dist-tests/api/ping.spec.js.map +1 -0
  95. package/dist-tests/helpers/auth.js +41 -0
  96. package/dist-tests/helpers/auth.js.map +1 -0
  97. package/dist-tests/helpers/env.js +11 -0
  98. package/dist-tests/helpers/env.js.map +1 -0
  99. package/docs/agent-hub-grooming.md +301 -0
  100. package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +438 -0
  101. package/docs/dashboards/dashboard-curl-smoke-tests.txt +146 -0
  102. package/docs/dashboards/delete-legacy-dashboard-metadata.sql +172 -0
  103. package/docs/datasource-introspection-ddl-analysis.md +326 -0
  104. package/docs/datasource-introspection-implementation-plan.md +306 -0
  105. package/docs/grouping-enhancements.md +89 -0
  106. package/docs/java-spring/README.md +3 -0
  107. package/docs/java-spring/solid-core-module-deep-dive-report.md +1317 -0
  108. package/docs/module-package-import-handoff.md +691 -0
  109. package/docs/seed-changes.md +65 -0
  110. package/docs/test-data-workflow.md +200 -0
  111. package/docs/type-declaration-import-issue.md +24 -0
  112. package/package.json +1 -1
  113. package/src/commands/migrate-removed-fields.command.ts +81 -0
  114. package/src/controllers/datasource-introspection.controller.ts +27 -1
  115. package/src/dtos/datasource-introspection-mapping.dto.ts +15 -0
  116. package/src/entities/{legacy-common-with-id.entity.ts → legacy-common-with-generated-id.entity.ts} +1 -1
  117. package/src/helpers/command.service.ts +10 -2
  118. package/src/helpers/model-metadata-helper.service.ts +1 -1
  119. package/src/helpers/nodemon-heartbeat.ts +59 -0
  120. package/src/index.ts +3 -2
  121. package/src/interfaces/datasource-introspection-provider.interface.ts +1 -0
  122. package/src/seeders/module-metadata-seeder.service.ts +118 -0
  123. package/src/seeders/seed-data/solid-core-metadata.json +121 -34
  124. package/src/services/api-key.service.ts +36 -36
  125. package/src/services/computed-fields/entity/concat-entity-computed-field-provider.service.ts +15 -1
  126. package/src/services/crud.service.ts +36 -11
  127. package/src/services/datasource-introspection/mssql-datasource-introspection-provider.service.ts +12 -0
  128. package/src/services/datasource-introspection/mysql-datasource-introspection-provider.service.ts +2 -0
  129. package/src/services/datasource-introspection/postgres-datasource-introspection-provider.service.ts +28 -15
  130. package/src/services/datasource-introspection.service.ts +653 -150
  131. package/src/services/import-transaction.service.ts +5 -0
  132. package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +2 -2
  133. package/src/services/model-metadata.service.ts +45 -1
  134. package/src/services/module-metadata.service.ts +35 -0
  135. package/src/services/removed-field-migration.service.ts +334 -0
  136. package/src/solid-core.module.ts +4 -0
  137. package/src/subscribers/audit.subscriber.ts +70 -5
  138. package/.claude/settings.local.json +0 -15
  139. package/CLAUDE.md +0 -26
  140. package/dist/entities/legacy-common-with-id.entity.d.ts.map +0 -1
  141. package/dist/entities/legacy-common-with-id.entity.js.map +0 -1
  142. package/dist/entities/legacy-common.entity.d.ts.map +0 -1
  143. package/dist/entities/legacy-common.entity.js.map +0 -1
  144. package/src/services/1.js +0 -6
  145. /package/src/entities/{legacy-common.entity.ts → legacy-common.entity-with-existing-id.entity.ts} +0 -0
@@ -1,5 +1,6 @@
1
1
  import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
2
2
  import * as fs from 'fs';
3
+ import * as os from 'os';
3
4
  import * as path from 'path';
4
5
  import { v4 as uuidv4 } from 'uuid';
5
6
 
@@ -20,6 +21,7 @@ import { CreateModuleMetadataDto } from '../dtos/create-module-metadata.dto';
20
21
  import { getDynamicModuleNamesBasedOnMetadata } from '../helpers/module.helper';
21
22
  import { SolidRegistry } from '../helpers/solid-registry';
22
23
  import { ActionMetadataService } from '../services/action-metadata.service';
24
+ import { ApiKeyService } from '../services/api-key.service';
23
25
  import { FieldMetadataService } from '../services/field-metadata.service';
24
26
  import { MediaStorageProviderMetadataService } from '../services/media-storage-provider-metadata.service';
25
27
  import { ModelMetadataService } from '../services/model-metadata.service';
@@ -33,6 +35,7 @@ import { ActionMetadata } from '../entities/action-metadata.entity';
33
35
  import { MenuItemMetadata } from '../entities/menu-item-metadata.entity';
34
36
  import { ModuleMetadata } from '../entities/module-metadata.entity';
35
37
  import { RoleMetadata } from '../entities/role-metadata.entity';
38
+ import { User } from '../entities/user.entity';
36
39
  import { MENU_ROLE_JOIN_TABLE_NAME, MENU_ROLE_JOIN_TABLE_NAME_MENU_COL, MENU_ROLE_JOIN_TABLE_NAME_ROLE_COL } from '../dtos/create-menu-item-metadata.dto';
37
40
  import { DEFAULT_SA_PASSWORD } from '../dtos/create-user.dto';
38
41
  import { SignUpDto } from '../dtos/sign-up.dto';
@@ -44,6 +47,7 @@ import { PermissionMetadataRepository } from 'src/repository/permission-metadata
44
47
  import { SavedFiltersRepository } from 'src/repository/saved-filters.repository';
45
48
  import { ScheduledJobRepository } from 'src/repository/scheduled-job.repository';
46
49
  import { SettingRepository } from 'src/repository/setting.repository';
50
+ import { UserApiKeyRepository } from 'src/repository/user-api-key.repository';
47
51
  import { CreateModelSequenceDto } from 'src/dtos/create-model-sequence.dto';
48
52
  import { ModelSequenceRepository } from 'src/repository/model-sequence.repository';
49
53
  import { LocaleRepository } from 'src/repository/locale.repository';
@@ -99,11 +103,13 @@ export class ModuleMetadataSeederService {
99
103
  private readonly roleService: RoleMetadataService,
100
104
  private readonly userService: UserService,
101
105
  private readonly authenticationService: AuthenticationService,
106
+ private readonly apiKeyService: ApiKeyService,
102
107
  private readonly solidActionService: ActionMetadataService,
103
108
  private readonly solidViewService: ViewMetadataService,
104
109
  private readonly emailTemplateService: EmailTemplateService,
105
110
  private readonly smsTemplateService: SmsTemplateService,
106
111
  private readonly listOfValuesService: ListOfValuesService,
112
+ private readonly userApiKeyRepository: UserApiKeyRepository,
107
113
  // @InjectRepository(PermissionMetadata)
108
114
  // private readonly permissionRepo: Repository<PermissionMetadata>,
109
115
  private readonly permissionRepo: PermissionMetadataRepository,
@@ -1364,6 +1370,7 @@ export class ModuleMetadataSeederService {
1364
1370
 
1365
1371
  for (let l = 0; l < users.length; l++) {
1366
1372
  const user: SignUpDto = users[l];
1373
+ const isSystemAdminUser = user.username === 'sa';
1367
1374
  let exisitingUser = await this.timeOperation('user-find-by-username', () => this.userService.findOneByUsername(user.username), {
1368
1375
  component: 'users',
1369
1376
  serviceCall: 'userService.findOneByUsername',
@@ -1373,14 +1380,32 @@ export class ModuleMetadataSeederService {
1373
1380
  if (user.username === 'sa') {
1374
1381
  user.password = DEFAULT_SA_PASSWORD;
1375
1382
  }
1383
+ if (isSystemAdminUser) {
1384
+ (user as SignUpDto & { isAllowedToGenerateApiKeys?: boolean }).isAllowedToGenerateApiKeys = true;
1385
+ }
1376
1386
 
1377
1387
  exisitingUser = await this.timeOperation('user-sign-up', () => this.authenticationService.signUp(user), {
1378
1388
  component: 'users',
1379
1389
  serviceCall: 'authenticationService.signUp',
1380
1390
  details: `username=${user.username}`,
1381
1391
  });
1392
+ if (isSystemAdminUser) {
1393
+ await this.timeOperation('seed-sa-api-key', async () => {
1394
+ const generatedApiKey = await this.apiKeyService.generate(exisitingUser.id, {
1395
+ name: 'Default SA API Key',
1396
+ });
1397
+ await this.writeSolidxAdminApiKeyConfig(generatedApiKey);
1398
+ }, {
1399
+ component: 'users',
1400
+ serviceCall: 'apiKeyService.generate',
1401
+ details: `username=${user.username}`,
1402
+ });
1403
+ }
1382
1404
  this.logger.log(`Newly created user ${user.username}`);
1383
1405
  }
1406
+ if (isSystemAdminUser) {
1407
+ await this.ensureSystemAdminApiKey(exisitingUser);
1408
+ }
1384
1409
  //FIXME: Create the user roles assignment logic here.
1385
1410
  // now add Roles to user.
1386
1411
  // for (let m = 0; m < roles.length; m++) {
@@ -1390,6 +1415,99 @@ export class ModuleMetadataSeederService {
1390
1415
  }
1391
1416
  }
1392
1417
 
1418
+ private async ensureSystemAdminApiKey(existingUser: { id: number; username: string; isAllowedToGenerateApiKeys?: boolean }) {
1419
+ if (!existingUser?.id) {
1420
+ return;
1421
+ }
1422
+
1423
+ if (!existingUser.isAllowedToGenerateApiKeys) {
1424
+ await this.timeOperation('enable-sa-api-key-generation', () => this.userApiKeyRepository.manager.update(User, { id: existingUser.id }, {
1425
+ isAllowedToGenerateApiKeys: true,
1426
+ }), {
1427
+ component: 'users',
1428
+ serviceCall: 'userRepository.update',
1429
+ details: `username=${existingUser.username}`,
1430
+ });
1431
+ existingUser.isAllowedToGenerateApiKeys = true;
1432
+ }
1433
+
1434
+ const existingDefaultKey = await this.timeOperation('find-sa-default-api-key', () => this.userApiKeyRepository.findOne({
1435
+ where: {
1436
+ user: { id: existingUser.id },
1437
+ name: 'Default SA API Key',
1438
+ },
1439
+ relations: {
1440
+ user: true,
1441
+ },
1442
+ }), {
1443
+ component: 'users',
1444
+ serviceCall: 'userApiKeyRepository.findOne',
1445
+ details: `username=${existingUser.username}`,
1446
+ });
1447
+
1448
+ if (existingDefaultKey) {
1449
+ return;
1450
+ }
1451
+
1452
+ await this.timeOperation('seed-sa-api-key', async () => {
1453
+ const generatedApiKey = await this.apiKeyService.generate(existingUser.id, {
1454
+ name: 'Default SA API Key',
1455
+ });
1456
+ await this.writeSolidxAdminApiKeyConfig(generatedApiKey);
1457
+ }, {
1458
+ component: 'users',
1459
+ serviceCall: 'apiKeyService.generate',
1460
+ details: `username=${existingUser.username}`,
1461
+ });
1462
+ }
1463
+
1464
+ private async writeSolidxAdminApiKeyConfig(generatedApiKey: {
1465
+ apiKey: string;
1466
+ record: {
1467
+ id: number;
1468
+ name: string;
1469
+ maskedKey: string;
1470
+ isActive: boolean;
1471
+ expiresAt: Date | null;
1472
+ createdAt?: Date;
1473
+ updatedAt?: Date;
1474
+ };
1475
+ }) {
1476
+ const solidxDir = path.join(os.homedir(), '.solidx');
1477
+ const configPath = path.join(solidxDir, 'mcp.json');
1478
+ await fs.promises.mkdir(solidxDir, { recursive: true });
1479
+
1480
+ let existingConfig: Record<string, any> = {};
1481
+
1482
+ if (fs.existsSync(configPath)) {
1483
+ const rawConfig = await fs.promises.readFile(configPath, 'utf8');
1484
+ if (rawConfig.trim()) {
1485
+ const parsedConfig = JSON.parse(rawConfig);
1486
+ if (parsedConfig && typeof parsedConfig === 'object' && !Array.isArray(parsedConfig)) {
1487
+ existingConfig = parsedConfig;
1488
+ } else {
1489
+ this.logger.warn(`Expected ${configPath} to contain a JSON object. Overwriting with a new object.`);
1490
+ }
1491
+ }
1492
+ }
1493
+
1494
+ const nextConfig = {
1495
+ ...existingConfig,
1496
+ solidxAdminApiKey: {
1497
+ id: generatedApiKey.record.id,
1498
+ name: generatedApiKey.record.name,
1499
+ apiKey: generatedApiKey.apiKey,
1500
+ maskedKey: generatedApiKey.record.maskedKey,
1501
+ isActive: generatedApiKey.record.isActive,
1502
+ expiresAt: generatedApiKey.record.expiresAt,
1503
+ createdAt: generatedApiKey.record.createdAt,
1504
+ updatedAt: generatedApiKey.record.updatedAt,
1505
+ },
1506
+ };
1507
+
1508
+ await fs.promises.writeFile(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, 'utf8');
1509
+ }
1510
+
1393
1511
  // OK
1394
1512
  private async seedModuleModelFields(moduleMetadata: CreateModuleMetadataDto): Promise<{ pruned: number; upserted: number }> {
1395
1513
  const fieldMetadataRepo = this.dataSource.getRepository(FieldMetadata);
@@ -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,
@@ -8737,12 +8746,15 @@
8737
8746
  48
8738
8747
  ],
8739
8748
  "enableGlobalSearch": true,
8740
- "create": true,
8741
- "edit": true,
8749
+ "create": false,
8750
+ "edit": false,
8742
8751
  "delete": true,
8752
+ "import": false,
8753
+ "export": false,
8743
8754
  "allowedViews": [
8744
8755
  "list",
8745
- "card"
8756
+ "card",
8757
+ "tree"
8746
8758
  ]
8747
8759
  },
8748
8760
  "children": [
@@ -9003,7 +9015,13 @@
9003
9015
  "enableGlobalSearch": true,
9004
9016
  "create": false,
9005
9017
  "edit": false,
9006
- "delete": false
9018
+ "delete": false,
9019
+ "import": false,
9020
+ "export": false,
9021
+ "allowedViews": [
9022
+ "list",
9023
+ "tree"
9024
+ ]
9007
9025
  },
9008
9026
  "children": [
9009
9027
  {
@@ -10095,15 +10113,11 @@
10095
10113
  "swimlanesCount": 5,
10096
10114
  "recordsInSwimlane": 10,
10097
10115
  "enableGlobalSearch": true,
10098
- "create": true,
10099
- "edit": true,
10100
- "delete": true,
10116
+ "create": false,
10117
+ "edit": false,
10118
+ "delete": false,
10101
10119
  "groupBy": "stage",
10102
- "draggable": false,
10103
- "allowedViews": [
10104
- "list",
10105
- "kanban"
10106
- ]
10120
+ "draggable": false
10107
10121
  },
10108
10122
  "children": [
10109
10123
  {
@@ -11929,7 +11943,11 @@
11929
11943
  "edit": false,
11930
11944
  "delete": false,
11931
11945
  "import": false,
11932
- "export": false
11946
+ "export": false,
11947
+ "allowedViews": [
11948
+ "list",
11949
+ "tree"
11950
+ ]
11933
11951
  },
11934
11952
  "children": [
11935
11953
  {
@@ -13424,7 +13442,13 @@
13424
13442
  "enableGlobalSearch": true,
13425
13443
  "create": false,
13426
13444
  "edit": true,
13427
- "delete": false
13445
+ "delete": false,
13446
+ "import": false,
13447
+ "export": false,
13448
+ "allowedViews": [
13449
+ "list",
13450
+ "tree"
13451
+ ]
13428
13452
  },
13429
13453
  "children": [
13430
13454
  {
@@ -13499,7 +13523,13 @@
13499
13523
  "enableGlobalSearch": true,
13500
13524
  "create": false,
13501
13525
  "edit": false,
13502
- "delete": false
13526
+ "delete": false,
13527
+ "import": false,
13528
+ "export": false,
13529
+ "allowedViews": [
13530
+ "list",
13531
+ "tree"
13532
+ ]
13503
13533
  },
13504
13534
  "children": [
13505
13535
  {
@@ -13583,7 +13613,13 @@
13583
13613
  "enableGlobalSearch": true,
13584
13614
  "create": false,
13585
13615
  "edit": false,
13586
- "delete": false
13616
+ "delete": false,
13617
+ "import": false,
13618
+ "export": false,
13619
+ "allowedViews": [
13620
+ "list",
13621
+ "tree"
13622
+ ]
13587
13623
  },
13588
13624
  "children": [
13589
13625
  {
@@ -13645,7 +13681,13 @@
13645
13681
  "enableGlobalSearch": true,
13646
13682
  "create": false,
13647
13683
  "edit": false,
13648
- "delete": false
13684
+ "delete": false,
13685
+ "import": false,
13686
+ "export": false,
13687
+ "allowedViews": [
13688
+ "list",
13689
+ "tree"
13690
+ ]
13649
13691
  },
13650
13692
  "children": [
13651
13693
  {
@@ -13714,7 +13756,13 @@
13714
13756
  "enableGlobalSearch": true,
13715
13757
  "create": false,
13716
13758
  "edit": false,
13717
- "delete": false
13759
+ "delete": true,
13760
+ "import": false,
13761
+ "export": false,
13762
+ "allowedViews": [
13763
+ "list",
13764
+ "tree"
13765
+ ]
13718
13766
  },
13719
13767
  "children": [
13720
13768
  {
@@ -13784,7 +13832,14 @@
13784
13832
  "enableGlobalSearch": true,
13785
13833
  "create": false,
13786
13834
  "edit": false,
13787
- "delete": false
13835
+ "delete": true,
13836
+ "import": false,
13837
+ "export": false,
13838
+ "allowedViews": [
13839
+ "list",
13840
+ "card",
13841
+ "tree"
13842
+ ]
13788
13843
  },
13789
13844
  "children": [
13790
13845
  {
@@ -13850,11 +13905,14 @@
13850
13905
  50
13851
13906
  ],
13852
13907
  "enableGlobalSearch": true,
13853
- "create": false,
13854
- "edit": false,
13855
- "delete": false,
13856
- "import": false,
13857
- "export": false
13908
+ "create": true,
13909
+ "edit": true,
13910
+ "delete": true,
13911
+ "import": true,
13912
+ "export": true,
13913
+ "allowedViews": [
13914
+ "list"
13915
+ ]
13858
13916
  },
13859
13917
  "children": [
13860
13918
  {
@@ -13889,7 +13947,11 @@
13889
13947
  "edit": false,
13890
13948
  "delete": false,
13891
13949
  "import": false,
13892
- "export": false
13950
+ "export": false,
13951
+ "allowedViews": [
13952
+ "list",
13953
+ "tree"
13954
+ ]
13893
13955
  },
13894
13956
  "children": [
13895
13957
  {
@@ -13951,7 +14013,11 @@
13951
14013
  "edit": false,
13952
14014
  "delete": false,
13953
14015
  "import": false,
13954
- "export": false
14016
+ "export": false,
14017
+ "allowedViews": [
14018
+ "list",
14019
+ "tree"
14020
+ ]
13955
14021
  },
13956
14022
  "children": [
13957
14023
  {
@@ -14020,7 +14086,11 @@
14020
14086
  "edit": true,
14021
14087
  "delete": true,
14022
14088
  "import": true,
14023
- "export": true
14089
+ "export": true,
14090
+ "allowedViews": [
14091
+ "list",
14092
+ "tree"
14093
+ ]
14024
14094
  },
14025
14095
  "children": [
14026
14096
  {
@@ -14080,7 +14150,11 @@
14080
14150
  "edit": false,
14081
14151
  "delete": false,
14082
14152
  "import": false,
14083
- "export": false
14153
+ "export": false,
14154
+ "allowedViews": [
14155
+ "list",
14156
+ "tree"
14157
+ ]
14084
14158
  },
14085
14159
  "children": [
14086
14160
  {
@@ -14140,7 +14214,11 @@
14140
14214
  "edit": false,
14141
14215
  "delete": false,
14142
14216
  "import": false,
14143
- "export": false
14217
+ "export": false,
14218
+ "allowedViews": [
14219
+ "list",
14220
+ "tree"
14221
+ ]
14144
14222
  },
14145
14223
  "children": [
14146
14224
  {
@@ -14210,7 +14288,11 @@
14210
14288
  "edit": false,
14211
14289
  "delete": false,
14212
14290
  "import": false,
14213
- "export": false
14291
+ "export": false,
14292
+ "allowedViews": [
14293
+ "list",
14294
+ "tree"
14295
+ ]
14214
14296
  },
14215
14297
  "children": [
14216
14298
  {
@@ -14279,7 +14361,12 @@
14279
14361
  "enableGlobalSearch": true,
14280
14362
  "create": true,
14281
14363
  "edit": true,
14282
- "delete": true
14364
+ "delete": true,
14365
+ "import": true,
14366
+ "export": true,
14367
+ "allowedViews": [
14368
+ "list"
14369
+ ]
14283
14370
  },
14284
14371
  "children": [
14285
14372
  {
@@ -26,53 +26,53 @@ export class ApiKeyService {
26
26
  private readonly permissionMetadataService: PermissionMetadataService,
27
27
  private readonly authenticationService: AuthenticationService,
28
28
  private readonly userRepository: UserRepository,
29
- ) {}
29
+ ) { }
30
30
 
31
- async generate(userId: number, dto: CreateApiKeyDto): Promise < { apiKey: string; record: UserApiKey } > {
32
- const user = await this.apiKeyRepository.manager.findOne(User, {
33
- where: { id: userId },
34
- select: ['id', 'isAllowedToGenerateApiKeys'],
35
- });
31
+ async generate(userId: number, dto: CreateApiKeyDto): Promise<{ apiKey: string; record: UserApiKey }> {
32
+ const user = await this.apiKeyRepository.manager.findOne(User, {
33
+ where: { id: userId },
34
+ select: ['id', 'isAllowedToGenerateApiKeys'],
35
+ });
36
36
 
37
- if(!user?.isAllowedToGenerateApiKeys) {
38
- throw new ForbiddenException('You are not allowed to generate API keys');
39
- }
37
+ if (!user?.isAllowedToGenerateApiKeys) {
38
+ throw new ForbiddenException('You are not allowed to generate API keys');
39
+ }
40
40
 
41
41
  const rawKey = 'sldx_' + randomBytes(32).toString('hex');
42
- const hashedKey = this.hash(rawKey);
43
- const maskedKey = 'sldx_****' + rawKey.slice(-4);
44
-
45
- const record = this.apiKeyRepository.create({
46
- name: dto.name,
47
- hashedKey,
48
- maskedKey,
49
- isActive: true,
50
- expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,
51
- user,
52
- });
42
+ const hashedKey = this.hash(rawKey);
43
+ const maskedKey = 'sldx_****' + rawKey.slice(-4);
44
+
45
+ const record = this.apiKeyRepository.create({
46
+ name: dto.name,
47
+ hashedKey,
48
+ maskedKey,
49
+ isActive: true,
50
+ expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,
51
+ user,
52
+ });
53
53
 
54
- await this.apiKeyRepository.save(record);
54
+ await this.apiKeyRepository.save(record);
55
55
 
56
- // Strip hashedKey from the returned record — maskedKey is all the UI needs
57
- delete(record as any).hashedKey;
56
+ // Strip hashedKey from the returned record — maskedKey is all the UI needs
57
+ delete (record as any).hashedKey;
58
58
 
59
- return { apiKey: rawKey, record };
60
- }
59
+ return { apiKey: rawKey, record };
60
+ }
61
61
 
62
- async validate(rawKey: string): Promise < ActiveUserData > {
63
- const hashedKey = this.hash(rawKey);
62
+ async validate(rawKey: string): Promise<ActiveUserData> {
63
+ const hashedKey = this.hash(rawKey);
64
64
 
65
- // Bypass security rules for auth validation — must find the key regardless of caller context
66
- const keyRecord = await this.apiKeyRepository.findOne({
67
- where: { hashedKey, isActive: true },
68
- relations: ['user', 'user.roles'],
69
- });
65
+ // Bypass security rules for auth validation — must find the key regardless of caller context
66
+ const keyRecord = await this.apiKeyRepository.findOne({
67
+ where: { hashedKey, isActive: true },
68
+ relations: ['user', 'user.roles'],
69
+ });
70
70
 
71
- if(!keyRecord) {
72
- throw new UnauthorizedException();
73
- }
71
+ if (!keyRecord) {
72
+ throw new UnauthorizedException();
73
+ }
74
74
 
75
- if(keyRecord.expiresAt && keyRecord.expiresAt < new Date()) {
75
+ if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) {
76
76
  throw new UnauthorizedException('API key expired');
77
77
  }
78
78
 
@@ -1,21 +1,29 @@
1
+ import dayjs from "dayjs";
1
2
  import { Injectable } from "@nestjs/common";
2
3
  import { kebabCase, get } from "lodash";
3
4
  import { ComputedFieldProvider } from "src/decorators/computed-field-provider.decorator";
4
5
  import { CommonEntity } from "src/entities/common.entity";
5
6
  import { ComputedFieldMetadata } from "src/helpers/solid-registry";
6
7
  import { IEntityPreComputeFieldProvider } from "src/interfaces";
8
+ import { SettingService } from "src/services/setting.service";
9
+ import type { SolidCoreSetting } from "src/services/settings/default-settings-provider.service";
7
10
 
8
11
 
9
12
  export interface ConcatComputedFieldContext {
10
13
  separator: string; // The separator to use between concatenated values
11
14
  fields: string[]; // The fields to concatenate
12
15
  slugify?: boolean; // Optional: if true, slugify each field value before concatenation
16
+ dateFormat?: string; // Optional: format to use for Date values. Defaults to the configured dateFormat setting
13
17
  }
14
18
 
15
19
  @ComputedFieldProvider()
16
20
  @Injectable()
17
21
  export class ConcatEntityComputedFieldProvider<T extends CommonEntity> implements IEntityPreComputeFieldProvider<T, ConcatComputedFieldContext> {
18
22
 
23
+ constructor(
24
+ private readonly settingService: SettingService,
25
+ ) { }
26
+
19
27
  name(): string {
20
28
  return "ConcatEntityComputedFieldProvider";
21
29
  }
@@ -29,6 +37,8 @@ export class ConcatEntityComputedFieldProvider<T extends CommonEntity> implement
29
37
  const separator = computedFieldValueProviderCtxt.separator ?? ' ';
30
38
  const fields: string[] = computedFieldValueProviderCtxt.fields ?? [];
31
39
  const slugify = computedFieldValueProviderCtxt.slugify ?? false;
40
+ const dateFormat = computedFieldValueProviderCtxt.dateFormat
41
+ ?? this.settingService.getConfigValue<SolidCoreSetting>("dateFormat");
32
42
 
33
43
  const parts: string[] = [];
34
44
 
@@ -38,6 +48,10 @@ export class ConcatEntityComputedFieldProvider<T extends CommonEntity> implement
38
48
  // normalize to string (skip null/undefined)
39
49
  if (val == null) continue;
40
50
 
51
+ if (val instanceof Date) {
52
+ val = dayjs(val).format(dateFormat);
53
+ }
54
+
41
55
  if (typeof val !== 'string') {
42
56
  val = String(val);
43
57
  }
@@ -58,4 +72,4 @@ export class ConcatEntityComputedFieldProvider<T extends CommonEntity> implement
58
72
  (triggerEntity as any)[computedFieldMetadata.fieldName] = concatenatedString;
59
73
  }
60
74
 
61
- }
75
+ }