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

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 (221) 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 +46 -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/controllers/service.controller.d.ts +1 -0
  10. package/dist/controllers/service.controller.d.ts.map +1 -1
  11. package/dist/controllers/service.controller.js +2 -2
  12. package/dist/controllers/service.controller.js.map +1 -1
  13. package/dist/dtos/datasource-introspection-mapping.dto.d.ts +5 -0
  14. package/dist/dtos/datasource-introspection-mapping.dto.d.ts.map +1 -1
  15. package/dist/dtos/datasource-introspection-mapping.dto.js +24 -2
  16. package/dist/dtos/datasource-introspection-mapping.dto.js.map +1 -1
  17. package/dist/entities/{legacy-common-with-id.entity.d.ts → legacy-common-with-generated-id.entity.d.ts} +2 -2
  18. package/dist/entities/legacy-common-with-generated-id.entity.d.ts.map +1 -0
  19. package/dist/entities/{legacy-common-with-id.entity.js → legacy-common-with-generated-id.entity.js} +4 -4
  20. package/dist/entities/legacy-common-with-generated-id.entity.js.map +1 -0
  21. package/dist/entities/{legacy-common.entity.d.ts → legacy-common.entity-with-existing-id.entity.d.ts} +1 -1
  22. package/dist/entities/legacy-common.entity-with-existing-id.entity.d.ts.map +1 -0
  23. package/dist/entities/{legacy-common.entity.js → legacy-common.entity-with-existing-id.entity.js} +1 -1
  24. package/dist/entities/legacy-common.entity-with-existing-id.entity.js.map +1 -0
  25. package/dist/helpers/command.service.d.ts +2 -0
  26. package/dist/helpers/command.service.d.ts.map +1 -1
  27. package/dist/helpers/command.service.js +6 -2
  28. package/dist/helpers/command.service.js.map +1 -1
  29. package/dist/helpers/environment.helper.d.ts +1 -0
  30. package/dist/helpers/environment.helper.d.ts.map +1 -1
  31. package/dist/helpers/environment.helper.js +4 -0
  32. package/dist/helpers/environment.helper.js.map +1 -1
  33. package/dist/helpers/field-crud-managers/IntFieldCrudManager.d.ts.map +1 -1
  34. package/dist/helpers/field-crud-managers/IntFieldCrudManager.js +4 -1
  35. package/dist/helpers/field-crud-managers/IntFieldCrudManager.js.map +1 -1
  36. package/dist/helpers/model-metadata-helper.service.d.ts +2 -1
  37. package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
  38. package/dist/helpers/model-metadata-helper.service.js +9 -5
  39. package/dist/helpers/model-metadata-helper.service.js.map +1 -1
  40. package/dist/helpers/module-metadata-helper.service.js +1 -1
  41. package/dist/helpers/module-metadata-helper.service.js.map +1 -1
  42. package/dist/helpers/nodemon-heartbeat.d.ts +5 -0
  43. package/dist/helpers/nodemon-heartbeat.d.ts.map +1 -0
  44. package/dist/helpers/nodemon-heartbeat.js +67 -0
  45. package/dist/helpers/nodemon-heartbeat.js.map +1 -0
  46. package/dist/helpers/solid-registry.d.ts +2 -1
  47. package/dist/helpers/solid-registry.d.ts.map +1 -1
  48. package/dist/helpers/solid-registry.js.map +1 -1
  49. package/dist/helpers/typeorm-db-helper.d.ts +1 -0
  50. package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
  51. package/dist/helpers/typeorm-db-helper.js +12 -0
  52. package/dist/helpers/typeorm-db-helper.js.map +1 -1
  53. package/dist/index.d.ts +3 -2
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +3 -2
  56. package/dist/index.js.map +1 -1
  57. package/dist/interfaces/datasource-introspection-provider.interface.d.ts +1 -0
  58. package/dist/interfaces/datasource-introspection-provider.interface.d.ts.map +1 -1
  59. package/dist/interfaces/datasource-introspection-provider.interface.js.map +1 -1
  60. package/dist/interfaces.d.ts +1 -0
  61. package/dist/interfaces.d.ts.map +1 -1
  62. package/dist/interfaces.js.map +1 -1
  63. package/dist/repository/scheduled-job.repository.d.ts +2 -2
  64. package/dist/repository/scheduled-job.repository.d.ts.map +1 -1
  65. package/dist/repository/scheduled-job.repository.js +6 -3
  66. package/dist/repository/scheduled-job.repository.js.map +1 -1
  67. package/dist/repository/security-rule.repository.d.ts +2 -2
  68. package/dist/repository/security-rule.repository.d.ts.map +1 -1
  69. package/dist/repository/security-rule.repository.js +6 -3
  70. package/dist/repository/security-rule.repository.js.map +1 -1
  71. package/dist/seeders/module-metadata-seeder.service.d.ts +11 -1
  72. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  73. package/dist/seeders/module-metadata-seeder.service.js +163 -3
  74. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  75. package/dist/seeders/seed-data/solid-core-metadata.json +128 -34
  76. package/dist/services/api-key.service.d.ts.map +1 -1
  77. package/dist/services/api-key.service.js.map +1 -1
  78. package/dist/services/authentication.service.d.ts +2 -0
  79. package/dist/services/authentication.service.d.ts.map +1 -1
  80. package/dist/services/authentication.service.js +32 -11
  81. package/dist/services/authentication.service.js.map +1 -1
  82. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
  83. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +7 -5
  84. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
  85. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts +4 -0
  86. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.d.ts.map +1 -1
  87. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js +18 -1
  88. package/dist/services/computed-fields/entity/concat-entity-computed-field-provider.service.js.map +1 -1
  89. package/dist/services/crud-helper.service.d.ts.map +1 -1
  90. package/dist/services/crud-helper.service.js +25 -12
  91. package/dist/services/crud-helper.service.js.map +1 -1
  92. package/dist/services/crud.service.d.ts +1 -0
  93. package/dist/services/crud.service.d.ts.map +1 -1
  94. package/dist/services/crud.service.js +27 -0
  95. package/dist/services/crud.service.js.map +1 -1
  96. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.d.ts.map +1 -1
  97. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js +12 -0
  98. package/dist/services/datasource-introspection/mssql-datasource-introspection-provider.service.js.map +1 -1
  99. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.d.ts.map +1 -1
  100. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js +2 -0
  101. package/dist/services/datasource-introspection/mysql-datasource-introspection-provider.service.js.map +1 -1
  102. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.d.ts.map +1 -1
  103. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js +28 -15
  104. package/dist/services/datasource-introspection/postgres-datasource-introspection-provider.service.js.map +1 -1
  105. package/dist/services/datasource-introspection.service.d.ts +63 -2
  106. package/dist/services/datasource-introspection.service.d.ts.map +1 -1
  107. package/dist/services/datasource-introspection.service.js +665 -188
  108. package/dist/services/datasource-introspection.service.js.map +1 -1
  109. package/dist/services/import-transaction.service.d.ts.map +1 -1
  110. package/dist/services/import-transaction.service.js +3 -0
  111. package/dist/services/import-transaction.service.js.map +1 -1
  112. package/dist/services/locale.service.d.ts +14 -0
  113. package/dist/services/locale.service.d.ts.map +1 -1
  114. package/dist/services/locale.service.js +83 -0
  115. package/dist/services/locale.service.js.map +1 -1
  116. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +10 -10
  117. package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
  118. package/dist/services/menu-item-metadata.service.d.ts.map +1 -1
  119. package/dist/services/menu-item-metadata.service.js +1 -0
  120. package/dist/services/menu-item-metadata.service.js.map +1 -1
  121. package/dist/services/model-metadata.service.d.ts +3 -0
  122. package/dist/services/model-metadata.service.d.ts.map +1 -1
  123. package/dist/services/model-metadata.service.js +78 -0
  124. package/dist/services/model-metadata.service.js.map +1 -1
  125. package/dist/services/module-metadata.service.d.ts.map +1 -1
  126. package/dist/services/module-metadata.service.js +28 -0
  127. package/dist/services/module-metadata.service.js.map +1 -1
  128. package/dist/services/removed-field-migration.service.d.ts +30 -0
  129. package/dist/services/removed-field-migration.service.d.ts.map +1 -0
  130. package/dist/services/removed-field-migration.service.js +319 -0
  131. package/dist/services/removed-field-migration.service.js.map +1 -0
  132. package/dist/services/role-metadata.service.d.ts +1 -0
  133. package/dist/services/role-metadata.service.d.ts.map +1 -1
  134. package/dist/services/role-metadata.service.js +23 -2
  135. package/dist/services/role-metadata.service.js.map +1 -1
  136. package/dist/services/settings/default-settings-provider.service.d.ts +244 -0
  137. package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
  138. package/dist/services/settings/default-settings-provider.service.js +120 -0
  139. package/dist/services/settings/default-settings-provider.service.js.map +1 -1
  140. package/dist/services/solid-ts-morph.service.d.ts +6 -0
  141. package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
  142. package/dist/services/solid-ts-morph.service.js +43 -0
  143. package/dist/services/solid-ts-morph.service.js.map +1 -1
  144. package/dist/services/view-metadata.service.d.ts.map +1 -1
  145. package/dist/services/view-metadata.service.js +4 -7
  146. package/dist/services/view-metadata.service.js.map +1 -1
  147. package/dist/solid-core.module.d.ts.map +1 -1
  148. package/dist/solid-core.module.js +4 -0
  149. package/dist/solid-core.module.js.map +1 -1
  150. package/dist/subscribers/audit.subscriber.d.ts +5 -1
  151. package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
  152. package/dist/subscribers/audit.subscriber.js +76 -12
  153. package/dist/subscribers/audit.subscriber.js.map +1 -1
  154. package/dist/subscribers/computed-entity-field.subscriber.d.ts +9 -1
  155. package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
  156. package/dist/subscribers/computed-entity-field.subscriber.js +45 -11
  157. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  158. package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
  159. package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
  160. package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
  161. package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
  162. package/dist/subscribers/scheduled-job.subscriber.d.ts.map +1 -1
  163. package/dist/subscribers/scheduled-job.subscriber.js +3 -2
  164. package/dist/subscribers/scheduled-job.subscriber.js.map +1 -1
  165. package/dist/subscribers/security-rule.subscriber.d.ts.map +1 -1
  166. package/dist/subscribers/security-rule.subscriber.js +5 -3
  167. package/dist/subscribers/security-rule.subscriber.js.map +1 -1
  168. package/package.json +1 -1
  169. package/src/commands/migrate-removed-fields.command.ts +81 -0
  170. package/src/controllers/datasource-introspection.controller.ts +27 -1
  171. package/src/controllers/service.controller.ts +3 -2
  172. package/src/dtos/datasource-introspection-mapping.dto.ts +15 -0
  173. package/src/entities/{legacy-common-with-id.entity.ts → legacy-common-with-generated-id.entity.ts} +1 -1
  174. package/src/helpers/command.service.ts +10 -2
  175. package/src/helpers/environment.helper.ts +11 -0
  176. package/src/helpers/field-crud-managers/IntFieldCrudManager.ts +4 -1
  177. package/src/helpers/model-metadata-helper.service.ts +8 -3
  178. package/src/helpers/module-metadata-helper.service.ts +1 -1
  179. package/src/helpers/nodemon-heartbeat.ts +59 -0
  180. package/src/helpers/solid-registry.ts +7 -1
  181. package/src/helpers/typeorm-db-helper.ts +15 -0
  182. package/src/index.ts +3 -2
  183. package/src/interfaces/datasource-introspection-provider.interface.ts +1 -0
  184. package/src/interfaces.ts +1 -0
  185. package/src/repository/scheduled-job.repository.ts +10 -4
  186. package/src/repository/security-rule.repository.ts +10 -4
  187. package/src/seeders/module-metadata-seeder.service.ts +192 -2
  188. package/src/seeders/seed-data/solid-core-metadata.json +128 -34
  189. package/src/services/api-key.service.ts +36 -36
  190. package/src/services/authentication.service.ts +46 -12
  191. package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +11 -5
  192. package/src/services/computed-fields/entity/concat-entity-computed-field-provider.service.ts +15 -1
  193. package/src/services/crud-helper.service.ts +25 -12
  194. package/src/services/crud.service.ts +36 -11
  195. package/src/services/datasource-introspection/mssql-datasource-introspection-provider.service.ts +12 -0
  196. package/src/services/datasource-introspection/mysql-datasource-introspection-provider.service.ts +2 -0
  197. package/src/services/datasource-introspection/postgres-datasource-introspection-provider.service.ts +28 -15
  198. package/src/services/datasource-introspection.service.ts +827 -164
  199. package/src/services/import-transaction.service.ts +5 -0
  200. package/src/services/locale.service.ts +111 -3
  201. package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +2 -2
  202. package/src/services/menu-item-metadata.service.ts +2 -1
  203. package/src/services/model-metadata.service.ts +109 -1
  204. package/src/services/module-metadata.service.ts +36 -0
  205. package/src/services/removed-field-migration.service.ts +334 -0
  206. package/src/services/role-metadata.service.ts +26 -2
  207. package/src/services/settings/default-settings-provider.service.ts +120 -0
  208. package/src/services/solid-ts-morph.service.ts +61 -1
  209. package/src/services/view-metadata.service.ts +4 -8
  210. package/src/solid-core.module.ts +4 -0
  211. package/src/subscribers/audit.subscriber.ts +101 -18
  212. package/src/subscribers/computed-entity-field.subscriber.ts +81 -28
  213. package/src/subscribers/created-by-updated-by.subscriber.ts +3 -0
  214. package/src/subscribers/field-metadata.subscriber.ts +3 -0
  215. package/src/subscribers/scheduled-job.subscriber.ts +3 -2
  216. package/src/subscribers/security-rule.subscriber.ts +8 -3
  217. package/dist/entities/legacy-common-with-id.entity.d.ts.map +0 -1
  218. package/dist/entities/legacy-common-with-id.entity.js.map +0 -1
  219. package/dist/entities/legacy-common.entity.d.ts.map +0 -1
  220. package/dist/entities/legacy-common.entity.js.map +0 -1
  221. /package/src/entities/{legacy-common.entity.ts → legacy-common.entity-with-existing-id.entity.ts} +0 -0
@@ -204,6 +204,11 @@ export class ImportTransactionService extends CRUDService<ImportTransaction> {
204
204
 
205
205
  // Iterate through the fields and populate the standard instructions
206
206
  for (const field of allFields) {
207
+
208
+ // Skip Computed fields
209
+ if (field.type === SolidFieldType.computed) {
210
+ continue;
211
+ }
207
212
  // Skip system fields
208
213
  if (systemFieldNames.includes(field.name)) {
209
214
  continue;
@@ -1,7 +1,7 @@
1
- import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';
1
+ import { BadRequestException, Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';
2
2
  import { ModuleRef } from "@nestjs/core";
3
3
  import { InjectEntityManager } from '@nestjs/typeorm';
4
- import { EntityManager } from 'typeorm';
4
+ import { EntityManager, In, IsNull, Not } from 'typeorm';
5
5
 
6
6
  import { Locale } from 'src/entities/locale.entity';
7
7
  import { SolidRegistry } from 'src/helpers/solid-registry';
@@ -31,7 +31,115 @@ export class LocaleService extends CRUDService<Locale> implements OnApplicationB
31
31
  // Load the security rules from the database
32
32
  this.loadLocales();
33
33
  }
34
- async loadLocales() {
34
+
35
+ private async assertCanSetAsDefault(currentLocaleId?: number) {
36
+ const defaultLocales = await this.repo.find({
37
+ where: {
38
+ isDefault: true,
39
+ } as any,
40
+ });
41
+
42
+ const conflictingDefaultLocale = defaultLocales.find(
43
+ (locale) => locale.id !== currentLocaleId
44
+ );
45
+
46
+ if (conflictingDefaultLocale) {
47
+ throw new BadRequestException(
48
+ `Locale "${conflictingDefaultLocale.displayName}" is already marked as default. Mark it as non-default first.`
49
+ );
50
+ }
51
+ }
52
+
53
+ override async create(createDto: any, files: Express.Multer.File[] = [], solidRequestContext: any = {}): Promise<Locale> {
54
+ if (createDto?.isDefault === true) {
55
+ await this.assertCanSetAsDefault();
56
+ }
57
+
58
+ const savedLocale = await super.create(createDto, files, solidRequestContext);
59
+ await this.loadLocales();
60
+ return savedLocale;
61
+ }
62
+
63
+ override async insertMany(createDtos: any[], filesArray: Express.Multer.File[][] = [], solidRequestContext: any = {}): Promise<Locale[]> {
64
+ const defaultLocalesInPayload = (createDtos || []).filter((dto) => dto?.isDefault === true);
65
+
66
+ if (defaultLocalesInPayload.length > 1) {
67
+ throw new BadRequestException(`Only one locale can be marked as default.`);
68
+ }
69
+
70
+ if (defaultLocalesInPayload.length === 1) {
71
+ await this.assertCanSetAsDefault();
72
+ }
73
+
74
+ const savedLocales = await super.insertMany(createDtos, filesArray, solidRequestContext);
75
+ await this.loadLocales();
76
+ return savedLocales;
77
+ }
78
+
79
+ override async update(id: number, updateDto: any, files: Express.Multer.File[] = [], isPartialUpdate: boolean = false, solidRequestContext: any = {}, isUpdate: boolean = false): Promise<Locale> {
80
+ if (updateDto?.isDefault === true) {
81
+ await this.assertCanSetAsDefault(id);
82
+ }
83
+
84
+ const savedLocale = await super.update(id, updateDto, files, isPartialUpdate, solidRequestContext, isUpdate);
85
+ await this.loadLocales();
86
+ return savedLocale;
87
+ }
88
+
89
+ override async recover(id: number, solidRequestContext: any = {}) {
90
+ const localeToRecover = await this.repo.findOne({
91
+ where: {
92
+ id,
93
+ deletedAt: Not(IsNull()),
94
+ } as any,
95
+ withDeleted: true,
96
+ });
97
+
98
+ if (localeToRecover?.isDefault) {
99
+ await this.assertCanSetAsDefault(id);
100
+ }
101
+
102
+ const recoveredLocale = await super.recover(id, solidRequestContext);
103
+ await this.loadLocales();
104
+ return recoveredLocale;
105
+ }
106
+
107
+ override async recoverMany(ids: number[], solidRequestContext: any = {}) {
108
+ const localesToRecover = await this.repo.find({
109
+ where: {
110
+ id: In(ids),
111
+ deletedAt: Not(IsNull()),
112
+ } as any,
113
+ withDeleted: true,
114
+ });
115
+
116
+ const defaultLocalesToRecover = localesToRecover.filter((locale) => locale.isDefault);
117
+ if (defaultLocalesToRecover.length > 1) {
118
+ throw new BadRequestException(`Only one locale can be marked as default.`);
119
+ }
120
+
121
+ if (defaultLocalesToRecover.length === 1) {
122
+ await this.assertCanSetAsDefault(defaultLocalesToRecover[0].id);
123
+ }
124
+
125
+ const recoveredLocales = await super.recoverMany(ids, solidRequestContext);
126
+ await this.loadLocales();
127
+ return recoveredLocales;
128
+ }
129
+
130
+ override async delete(id: number, solidRequestContext: any = {}) {
131
+ const deletedLocale = await super.delete(id, solidRequestContext);
132
+ await this.loadLocales();
133
+ return deletedLocale;
134
+ }
135
+
136
+ override async deleteMany(ids: number[], solidRequestContext: any = {}) {
137
+ const deletedLocales = await super.deleteMany(ids, solidRequestContext);
138
+ await this.loadLocales();
139
+ return deletedLocales;
140
+ }
141
+
142
+ async loadLocales() {
35
143
  const locales = await this.repo.find();
36
144
  this.logger.debug(`Loaded ${locales.length} locales into registry`);
37
145
  this.solidRegistry.registerlocales(locales);
@@ -2,8 +2,8 @@ import { Injectable, Logger } from "@nestjs/common";
2
2
  import { ConfigService } from "@nestjs/config";
3
3
  import { CommonEntity } from "src/entities/common.entity";
4
4
  import { FieldMetadata } from "src/entities/field-metadata.entity";
5
- import { LegacyCommonEntityWithExistingId } from "src/entities/legacy-common.entity";
6
- import { LegacyCommonEntityWithGeneratedId } from "src/entities/legacy-common-with-id.entity";
5
+ import { LegacyCommonEntityWithExistingId } from "src/entities/legacy-common.entity-with-existing-id.entity";
6
+ import { LegacyCommonEntityWithGeneratedId } from "src/entities/legacy-common-with-generated-id.entity";
7
7
  import { Media } from "src/entities/media.entity";
8
8
  import { MediaStorageProvider } from "src/interfaces";
9
9
  import { DiskFileService, S3FileService } from "src/services/file";
@@ -154,7 +154,7 @@ export class MenuItemMetadataService extends CRUDService<MenuItemMetadata> {
154
154
  if (!i.parentMenuItem) {
155
155
  return true
156
156
  } else {
157
- if(i.action.type === 'custom'){
157
+ if (i.action.type === 'custom') {
158
158
  return true;
159
159
  }
160
160
  return this.crudHelperService.hasReadPermissionOnModel(activeUser, i.action.model.singularName)
@@ -203,6 +203,7 @@ export class MenuItemMetadataService extends CRUDService<MenuItemMetadata> {
203
203
  key: rootItem.name.toLowerCase().replace(/\s+/g, '-'),
204
204
  icon: rootItem.iconName,
205
205
  // iconVariant : rootItem.iconVariant
206
+ isSystem: (rootItem.action?.model?.isSystem ?? false) || rootItem.module?.name === "solid-core",
206
207
  }
207
208
  if (children.length > 0) {
208
209
  data["children"] = await this.buildMenuTree(children, allMenuItems, activeUser);
@@ -1,6 +1,7 @@
1
1
  import { BadRequestException, forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
2
2
  import { InjectDataSource } from '@nestjs/typeorm';
3
3
  import * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await
4
+ import { existsSync } from 'fs';
4
5
  import * as path from 'path';
5
6
  import { DataSource, EntityManager, In, Repository, SelectQueryBuilder } from 'typeorm';
6
7
  import { CreateModelMetadataDto } from '../dtos/create-model-metadata.dto';
@@ -27,6 +28,8 @@ import { PermissionMetadata } from '../entities/permission-metadata.entity';
27
28
  import { RoleMetadata } from '../entities/role-metadata.entity';
28
29
  import { ViewMetadata } from '../entities/view-metadata.entity';
29
30
  import { CommandService } from '../helpers/command.service';
31
+ import { isEmbeddedDb } from '../helpers/environment.helper';
32
+ import { startNodemonHeartbeat } from '../helpers/nodemon-heartbeat';
30
33
  import {
31
34
  REFRESH_MODEL_COMMAND,
32
35
  REMOVE_FIELDS_COMMAND,
@@ -743,10 +746,72 @@ export class ModelMetadataService {
743
746
  }
744
747
  }
745
748
 
749
+ await this.cleanupAssociatedTypeormDatasourceFiles(modelEntity, modulePath);
750
+
746
751
  // - | Drop database table | Removes the database table from the DB, this is a very risky step. Best to review all relations to other models etc and then do this manually | Manual (X)
747
752
 
748
753
  }
749
754
 
755
+ private resolveSolidApiRoot(): string | null {
756
+ const cwd = process.cwd();
757
+ const candidates = [
758
+ cwd,
759
+ path.join(cwd, 'solid-api'),
760
+ ];
761
+
762
+ for (const candidate of candidates) {
763
+ const srcRoot = path.join(candidate, 'src');
764
+ if (existsSync(srcRoot)) {
765
+ return candidate;
766
+ }
767
+ }
768
+
769
+ return null;
770
+ }
771
+
772
+ private async cleanupAssociatedTypeormDatasourceFiles(modelEntity: ModelMetadata, modulePath?: string | null) {
773
+ if (!modulePath) {
774
+ return;
775
+ }
776
+
777
+ const solidApiRoot = this.resolveSolidApiRoot();
778
+ if (!solidApiRoot) {
779
+ this.logger.warn(`Unable to locate consuming solid-api workspace while cleaning datasource files for model '${modelEntity.singularName}'`);
780
+ return;
781
+ }
782
+
783
+ const srcRoot = path.join(solidApiRoot, 'src');
784
+ const srcEntries = await fs.readdir(srcRoot).catch(() => []);
785
+ const datasourceFiles = srcEntries
786
+ .filter((entry) => /^typeorm-.*-datasource\.ts$/.test(entry))
787
+ .map((entry) => path.join(srcRoot, entry));
788
+
789
+ if (datasourceFiles.length === 0) {
790
+ return;
791
+ }
792
+
793
+ const moduleDirName = path.basename(modulePath);
794
+ const entityClassName = classify(modelEntity.singularName);
795
+ const entityImportPath = `./${moduleDirName}/entities/${kebabCase(modelEntity.singularName)}.entity`;
796
+
797
+ this.logger.log(`Scanning ${datasourceFiles.length} TypeORM datasource file(s) for model '${modelEntity.singularName}' cleanup`);
798
+
799
+ try {
800
+ this.solidTsMorphService.begin();
801
+ for (const datasourceFile of datasourceFiles) {
802
+ this.solidTsMorphService.cleanupTypeormDatasourceEntity(
803
+ datasourceFile,
804
+ entityImportPath,
805
+ entityClassName,
806
+ );
807
+ }
808
+ await this.solidTsMorphService.commit();
809
+ } catch (error: any) {
810
+ this.solidTsMorphService.rollback();
811
+ this.logger.error(`Failed to clean datasource files for model '${modelEntity.singularName}':`, error);
812
+ }
813
+ }
814
+
750
815
  private async cleanupAssociatedViewsActionsAndMenus(modelId: number) {
751
816
  const viewRepo = this.dataSource.getRepository(ViewMetadata);
752
817
  const actionRepo = this.dataSource.getRepository(ActionMetadata);
@@ -967,6 +1032,26 @@ export class ModelMetadataService {
967
1032
  @DisallowInProduction()
968
1033
  async generateCodeViaCtl(modelId: number): Promise<string> {
969
1034
  const model = await this.findOne(modelId);
1035
+ const isEmbedded = isEmbeddedDb();
1036
+
1037
+ // When using an embedded PGlite database, the single-connection limit means
1038
+ // a spawned `solid refresh-model` subprocess cannot get its own DB connection
1039
+ // while the API server is already holding it. Fall back to in-process code
1040
+ // generation (which reuses the existing connection).
1041
+ if (isEmbedded) {
1042
+ this.logger.log('Embedded database detected — generating API code in-process');
1043
+ // Prevent nodemon from restarting the server while schematics write files.
1044
+ const heartbeat = startNodemonHeartbeat(path.join(process.cwd(), 'src'));
1045
+ try {
1046
+ return await this.handleGenerateCode({
1047
+ modelUserKey: model.singularName,
1048
+ dryRun: false,
1049
+ });
1050
+ } finally {
1051
+ heartbeat.stop();
1052
+ }
1053
+ }
1054
+
970
1055
  return this.commandService.executeCommandWithArgs({
971
1056
  command: 'npx',
972
1057
  args: ['@solidxai/solidctl@latest', 'generate', 'model', `--name=${model.singularName}`],
@@ -1478,7 +1563,7 @@ export class ModelMetadataService {
1478
1563
  //Filter out the fields by id
1479
1564
  const fieldsForRemoval = model.fields.filter((field) => options.fieldIdsForRemoval.includes(+field.id));
1480
1565
  const removeOutput = await this.executeRemoveFieldsCommand(model, fieldsForRemoval, options.dryRun);
1481
-
1566
+ const migrationOutput = await this.executeMigrationRemoveFieldsCommand(model, fieldsForRemoval, options.dryRun);
1482
1567
  // Remove the fields from the database as well. This also checks, if the field is marked for removal
1483
1568
  for (const field of fieldsForRemoval) {
1484
1569
  if (field.isMarkedForRemoval) {
@@ -1515,6 +1600,13 @@ export class ModelMetadataService {
1515
1600
 
1516
1601
  return removeOutput;
1517
1602
  }
1603
+ // model-metadata.service.ts mein naya method add karo
1604
+ // async executeRemoveFieldsWithModel(model: ModelMetadata, fieldNames: string[], dryRun = false,) {
1605
+ // const fieldsForRemoval = model.fields.filter(
1606
+ // field => fieldNames.includes(field.name)
1607
+ // );
1608
+ // return this.executeRemoveFieldsCommand(model, fieldsForRemoval, dryRun);
1609
+ // }
1518
1610
 
1519
1611
  async generateModelCode(options: CodeGenerationOptions): Promise<string> {
1520
1612
  if (!options.modelId && !options.modelUserKey) {
@@ -1563,6 +1655,22 @@ export class ModelMetadataService {
1563
1655
  return output;
1564
1656
  }
1565
1657
 
1658
+ private async executeMigrationRemoveFieldsCommand(model: ModelMetadata, fieldsForRemoval: FieldMetadata[], dryRun: boolean = false,): Promise<string> {
1659
+ if (!fieldsForRemoval || fieldsForRemoval.length === 0) {
1660
+ return "";
1661
+ }
1662
+
1663
+ const output = await this.commandService.executeCommandWithArgs({
1664
+ command: 'npx',
1665
+ args: ['@solidxai/solidctl@latest', 'migration', '-n', model.singularName, 'remove-field', ...(dryRun ? [] : ['--apply'])],
1666
+ cwd: path.join(process.cwd(), '..'),
1667
+ });
1668
+
1669
+ this.logger.debug(`Schematic output : ${output}`);
1670
+ return output;
1671
+ }
1672
+
1673
+
1566
1674
  async updateUserKey(data: any) {
1567
1675
  const { modelName, fieldName } = data;
1568
1676
 
@@ -26,6 +26,8 @@ import {
26
26
  } from '../helpers/schematic.service';
27
27
  import { CommandService } from '../helpers/command.service';
28
28
  import { SolidRegistry } from '../helpers/solid-registry';
29
+ import { isEmbeddedDb } from '../helpers/environment.helper';
30
+ import { startNodemonHeartbeat } from '../helpers/nodemon-heartbeat';
29
31
  import { CodeGenerationOptions, ModuleMetadataConfiguration } from '../interfaces';
30
32
  import { CrudHelperService } from './crud-helper.service';
31
33
  import { ModelMetadataService } from './model-metadata.service';
@@ -534,6 +536,40 @@ export class ModuleMetadataService {
534
536
  @DisallowInProduction()
535
537
  async generateCodeViaCtl(moduleId: number): Promise<string> {
536
538
  const module = await this.findOne(moduleId);
539
+ const isEmbedded = isEmbeddedDb();
540
+
541
+ // When using an embedded PGlite database, the single-connection limit means
542
+ // a spawned `solid refresh-module` subprocess cannot get its own DB connection
543
+ // while the API server is already holding it. Fall back to in-process code
544
+ // generation (which reuses the existing connection) and only spawn solidctl
545
+ // for the UI module scaffold (which does not need a database connection).
546
+ if (isEmbedded) {
547
+ this.logger.log('Embedded database detected — generating API code in-process');
548
+ // Prevent nodemon from restarting the server while schematics write files.
549
+ // The heartbeat touches a watched file every 1.5 s (nodemon delay is 2 s),
550
+ // keeping the delay from expiring during DB queries between schematic runs.
551
+ const heartbeat = startNodemonHeartbeat(path.join(process.cwd(), 'src'));
552
+ try {
553
+ const apiOutput = await this.generateCode({
554
+ moduleUserKey: module.name,
555
+ dryRun: false,
556
+ });
557
+ let uiOutput = '';
558
+ try {
559
+ uiOutput = await this.commandService.executeCommandWithArgs({
560
+ command: 'npx',
561
+ args: ['@solidxai/solidctl@latest', 'generate', 'ui-module', `--name=${module.name}`],
562
+ cwd: path.join(process.cwd(), '..'),
563
+ });
564
+ } catch (error) {
565
+ this.logger.warn('UI module scaffold failed (solidctl may be outdated); API code was generated successfully.');
566
+ }
567
+ return `${apiOutput}\n${uiOutput}`;
568
+ } finally {
569
+ heartbeat.stop();
570
+ }
571
+ }
572
+
537
573
  return this.commandService.executeCommandWithArgs({
538
574
  command: 'npx',
539
575
  args: ['@solidxai/solidctl@latest', 'generate', 'module', `--name=${module.name}`],