@solidxai/core 0.1.9-beta.6 → 0.1.9-beta.8

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 (254) hide show
  1. package/dist/constants/chatter-message.constants.d.ts +6 -0
  2. package/dist/constants/chatter-message.constants.d.ts.map +1 -1
  3. package/dist/constants/chatter-message.constants.js +7 -1
  4. package/dist/constants/chatter-message.constants.js.map +1 -1
  5. package/dist/controllers/authentication.controller.d.ts +12 -0
  6. package/dist/controllers/authentication.controller.d.ts.map +1 -1
  7. package/dist/controllers/authentication.controller.js +13 -0
  8. package/dist/controllers/authentication.controller.js.map +1 -1
  9. package/dist/controllers/chatter-message.controller.d.ts +1 -0
  10. package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
  11. package/dist/controllers/chatter-message.controller.js +12 -0
  12. package/dist/controllers/chatter-message.controller.js.map +1 -1
  13. package/dist/controllers/facebook-authentication.controller.d.ts +27 -0
  14. package/dist/controllers/facebook-authentication.controller.d.ts.map +1 -0
  15. package/dist/controllers/facebook-authentication.controller.js +117 -0
  16. package/dist/controllers/facebook-authentication.controller.js.map +1 -0
  17. package/dist/controllers/menu-item-metadata.controller.d.ts +1 -0
  18. package/dist/controllers/menu-item-metadata.controller.d.ts.map +1 -1
  19. package/dist/controllers/menu-item-metadata.controller.js +15 -0
  20. package/dist/controllers/menu-item-metadata.controller.js.map +1 -1
  21. package/dist/controllers/microsoft-authentication.controller.d.ts +27 -0
  22. package/dist/controllers/microsoft-authentication.controller.d.ts.map +1 -0
  23. package/dist/controllers/microsoft-authentication.controller.js +118 -0
  24. package/dist/controllers/microsoft-authentication.controller.js.map +1 -0
  25. package/dist/controllers/setting.controller.d.ts +2 -2
  26. package/dist/controllers/setting.controller.js +2 -2
  27. package/dist/decorators/auth.decorator.d.ts.map +1 -1
  28. package/dist/decorators/computed-field-provider.decorator.d.ts.map +1 -1
  29. package/dist/decorators/dashboard-question-data-provider.decorator.d.ts.map +1 -1
  30. package/dist/decorators/dashboard-selection-provider.decorator.d.ts.map +1 -1
  31. package/dist/decorators/disallow-in-production.decorator.d.ts.map +1 -1
  32. package/dist/decorators/error-codes-provider.decorator.d.ts.map +1 -1
  33. package/dist/decorators/extension-user-creation-provider.decorator.d.ts.map +1 -1
  34. package/dist/decorators/is-not-in-enum.decorator.d.ts.map +1 -1
  35. package/dist/decorators/mail-provider.decorator.d.ts.map +1 -1
  36. package/dist/decorators/roles.decorator.d.ts.map +1 -1
  37. package/dist/decorators/scheduled-job-provider.decorator.d.ts.map +1 -1
  38. package/dist/decorators/security-rule-config-provider.decorator.d.ts.map +1 -1
  39. package/dist/decorators/selection-provider.decorator.d.ts.map +1 -1
  40. package/dist/decorators/sms-provider.decorator.d.ts.map +1 -1
  41. package/dist/decorators/solid-database-module.decorator.d.ts.map +1 -1
  42. package/dist/decorators/whatsapp-provider.decorator.d.ts.map +1 -1
  43. package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
  44. package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
  45. package/dist/dtos/create-chatter-message.dto.js +7 -1
  46. package/dist/dtos/create-chatter-message.dto.js.map +1 -1
  47. package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
  48. package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
  49. package/dist/dtos/post-chatter-message.dto.js +6 -1
  50. package/dist/dtos/post-chatter-message.dto.js.map +1 -1
  51. package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
  52. package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
  53. package/dist/dtos/update-chatter-message.dto.js +7 -1
  54. package/dist/dtos/update-chatter-message.dto.js.map +1 -1
  55. package/dist/entities/chatter-message.entity.d.ts +1 -0
  56. package/dist/entities/chatter-message.entity.d.ts.map +1 -1
  57. package/dist/entities/chatter-message.entity.js +5 -1
  58. package/dist/entities/chatter-message.entity.js.map +1 -1
  59. package/dist/entities/user.entity.d.ts +8 -0
  60. package/dist/entities/user.entity.d.ts.map +1 -1
  61. package/dist/entities/user.entity.js +33 -1
  62. package/dist/entities/user.entity.js.map +1 -1
  63. package/dist/helpers/cors.helper.js +1 -1
  64. package/dist/helpers/cors.helper.js.map +1 -1
  65. package/dist/helpers/facebook-oauth.helper.d.ts +8 -0
  66. package/dist/helpers/facebook-oauth.helper.d.ts.map +1 -0
  67. package/dist/helpers/facebook-oauth.helper.js +11 -0
  68. package/dist/helpers/facebook-oauth.helper.js.map +1 -0
  69. package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.js +5 -5
  70. package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.js.map +1 -1
  71. package/dist/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.d.ts.map +1 -1
  72. package/dist/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.js +2 -2
  73. package/dist/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.js.map +1 -1
  74. package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.js +5 -5
  75. package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.js.map +1 -1
  76. package/dist/helpers/microsoft-oauth.helper.d.ts +9 -0
  77. package/dist/helpers/microsoft-oauth.helper.d.ts.map +1 -0
  78. package/dist/helpers/microsoft-oauth.helper.js +12 -0
  79. package/dist/helpers/microsoft-oauth.helper.js.map +1 -0
  80. package/dist/helpers/module-metadata-helper.service.js +3 -3
  81. package/dist/helpers/module-metadata-helper.service.js.map +1 -1
  82. package/dist/helpers/security.helper.d.ts.map +1 -1
  83. package/dist/helpers/string.helper.d.ts +1 -0
  84. package/dist/helpers/string.helper.d.ts.map +1 -1
  85. package/dist/helpers/string.helper.js +4 -1
  86. package/dist/helpers/string.helper.js.map +1 -1
  87. package/dist/helpers/user-helper.d.ts.map +1 -1
  88. package/dist/helpers/user-helper.js +4 -0
  89. package/dist/helpers/user-helper.js.map +1 -1
  90. package/dist/index.d.ts +2 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +2 -0
  93. package/dist/index.js.map +1 -1
  94. package/dist/interfaces.d.ts +19 -0
  95. package/dist/interfaces.d.ts.map +1 -1
  96. package/dist/interfaces.js.map +1 -1
  97. package/dist/passport-strategies/facebook-oauth.strategy.d.ts +14 -0
  98. package/dist/passport-strategies/facebook-oauth.strategy.d.ts.map +1 -0
  99. package/dist/passport-strategies/facebook-oauth.strategy.js +73 -0
  100. package/dist/passport-strategies/facebook-oauth.strategy.js.map +1 -0
  101. package/dist/passport-strategies/microsoft-oauth.strategy.d.ts +14 -0
  102. package/dist/passport-strategies/microsoft-oauth.strategy.d.ts.map +1 -0
  103. package/dist/passport-strategies/microsoft-oauth.strategy.js +77 -0
  104. package/dist/passport-strategies/microsoft-oauth.strategy.js.map +1 -0
  105. package/dist/repository/chatter-message-details.repository.d.ts.map +1 -1
  106. package/dist/repository/chatter-message-details.repository.js +7 -6
  107. package/dist/repository/chatter-message-details.repository.js.map +1 -1
  108. package/dist/repository/chatter-message.repository.d.ts.map +1 -1
  109. package/dist/repository/chatter-message.repository.js +4 -4
  110. package/dist/repository/chatter-message.repository.js.map +1 -1
  111. package/dist/repository/solid-base.repository.js +2 -2
  112. package/dist/repository/solid-base.repository.js.map +1 -1
  113. package/dist/seeders/module-test-data.service.js +4 -4
  114. package/dist/seeders/module-test-data.service.js.map +1 -1
  115. package/dist/seeders/seed-data/solid-core-metadata.json +27 -58
  116. package/dist/services/api-key.service.d.ts +17 -1
  117. package/dist/services/api-key.service.d.ts.map +1 -1
  118. package/dist/services/api-key.service.js +38 -2
  119. package/dist/services/api-key.service.js.map +1 -1
  120. package/dist/services/authentication.service.d.ts +51 -16
  121. package/dist/services/authentication.service.d.ts.map +1 -1
  122. package/dist/services/authentication.service.js +318 -150
  123. package/dist/services/authentication.service.js.map +1 -1
  124. package/dist/services/chatter-message.service.d.ts +1 -0
  125. package/dist/services/chatter-message.service.d.ts.map +1 -1
  126. package/dist/services/chatter-message.service.js +17 -0
  127. package/dist/services/chatter-message.service.js.map +1 -1
  128. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts.map +1 -1
  129. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js +2 -2
  130. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js.map +1 -1
  131. package/dist/services/crud-helper.service.d.ts.map +1 -1
  132. package/dist/services/crud-helper.service.js +9 -9
  133. package/dist/services/crud-helper.service.js.map +1 -1
  134. package/dist/services/export-transaction.service.d.ts.map +1 -1
  135. package/dist/services/export-transaction.service.js +4 -3
  136. package/dist/services/export-transaction.service.js.map +1 -1
  137. package/dist/services/field-metadata.service.d.ts.map +1 -1
  138. package/dist/services/field-metadata.service.js +7 -7
  139. package/dist/services/field-metadata.service.js.map +1 -1
  140. package/dist/services/fixtures.service.js +2 -2
  141. package/dist/services/fixtures.service.js.map +1 -1
  142. package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.d.ts.map +1 -1
  143. package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.js +2 -2
  144. package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.js.map +1 -1
  145. package/dist/services/import-transaction.service.d.ts.map +1 -1
  146. package/dist/services/import-transaction.service.js +2 -2
  147. package/dist/services/import-transaction.service.js.map +1 -1
  148. package/dist/services/menu-item-metadata.service.js +2 -2
  149. package/dist/services/menu-item-metadata.service.js.map +1 -1
  150. package/dist/services/model-metadata.service.d.ts.map +1 -1
  151. package/dist/services/model-metadata.service.js +12 -11
  152. package/dist/services/model-metadata.service.js.map +1 -1
  153. package/dist/services/module-metadata.service.d.ts.map +1 -1
  154. package/dist/services/module-metadata.service.js +2 -2
  155. package/dist/services/module-metadata.service.js.map +1 -1
  156. package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
  157. package/dist/services/queues/publisher-factory.service.js +2 -2
  158. package/dist/services/queues/publisher-factory.service.js.map +1 -1
  159. package/dist/services/selection-providers/pseudo-foreign-key-selection-provider.service.js +3 -3
  160. package/dist/services/selection-providers/pseudo-foreign-key-selection-provider.service.js.map +1 -1
  161. package/dist/services/setting.service.d.ts +5 -2
  162. package/dist/services/setting.service.d.ts.map +1 -1
  163. package/dist/services/setting.service.js +51 -6
  164. package/dist/services/setting.service.js.map +1 -1
  165. package/dist/services/settings/default-settings-provider.service.d.ts +830 -0
  166. package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
  167. package/dist/services/settings/default-settings-provider.service.js +1033 -117
  168. package/dist/services/settings/default-settings-provider.service.js.map +1 -1
  169. package/dist/services/solid-introspect.service.js +2 -2
  170. package/dist/services/solid-introspect.service.js.map +1 -1
  171. package/dist/services/user.service.d.ts +2 -0
  172. package/dist/services/user.service.d.ts.map +1 -1
  173. package/dist/services/user.service.js +72 -0
  174. package/dist/services/user.service.js.map +1 -1
  175. package/dist/services/view-metadata.service.d.ts.map +1 -1
  176. package/dist/services/view-metadata.service.js +2 -2
  177. package/dist/services/view-metadata.service.js.map +1 -1
  178. package/dist/solid-core.module.d.ts.map +1 -1
  179. package/dist/solid-core.module.js +11 -3
  180. package/dist/solid-core.module.js.map +1 -1
  181. package/dist/subscribers/computed-entity-field.subscriber.js +6 -6
  182. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  183. package/dist/transformers/array-transformer.d.ts.map +1 -1
  184. package/dist/transformers/boolean-transformer.d.ts.map +1 -1
  185. package/dist/transformers/datetime-transformer.d.ts.map +1 -1
  186. package/dist/transformers/integer-transformer.d.ts.map +1 -1
  187. package/dist/validators/is-parsable-int.d.ts.map +1 -1
  188. package/dist-tests/api/authenticate.spec.js +119 -0
  189. package/dist-tests/api/authenticate.spec.js.map +1 -0
  190. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  191. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  192. package/dist-tests/api/ping.spec.js +21 -0
  193. package/dist-tests/api/ping.spec.js.map +1 -0
  194. package/dist-tests/helpers/auth.js +41 -0
  195. package/dist-tests/helpers/auth.js.map +1 -0
  196. package/dist-tests/helpers/env.js +11 -0
  197. package/dist-tests/helpers/env.js.map +1 -0
  198. package/docs/java-spring/README.md +3 -0
  199. package/docs/java-spring/solid-core-module-deep-dive-report.md +1317 -0
  200. package/nest +0 -0
  201. package/package.json +7 -2
  202. package/src/constants/chatter-message.constants.ts +7 -0
  203. package/src/controllers/authentication.controller.ts +8 -1
  204. package/src/controllers/chatter-message.controller.ts +6 -0
  205. package/src/controllers/facebook-authentication.controller.ts +113 -0
  206. package/src/controllers/menu-item-metadata.controller.ts +21 -15
  207. package/src/controllers/microsoft-authentication.controller.ts +116 -0
  208. package/src/dtos/create-chatter-message.dto.ts +11 -0
  209. package/src/dtos/post-chatter-message.dto.ts +4 -0
  210. package/src/dtos/update-chatter-message.dto.ts +13 -1
  211. package/src/entities/chatter-message.entity.ts +4 -1
  212. package/src/entities/user.entity.ts +32 -0
  213. package/src/helpers/cors.helper.ts +1 -1
  214. package/src/helpers/facebook-oauth.helper.ts +17 -0
  215. package/src/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.ts +1 -1
  216. package/src/helpers/field-crud-managers/ManyToOneRelationFieldCrudManager.ts +1 -2
  217. package/src/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.ts +1 -1
  218. package/src/helpers/microsoft-oauth.helper.ts +19 -0
  219. package/src/helpers/module-metadata-helper.service.ts +3 -3
  220. package/src/helpers/string.helper.ts +3 -0
  221. package/src/helpers/user-helper.ts +4 -0
  222. package/src/index.ts +2 -0
  223. package/src/interfaces.ts +32 -1
  224. package/src/passport-strategies/facebook-oauth.strategy.ts +64 -0
  225. package/src/passport-strategies/microsoft-oauth.strategy.ts +70 -0
  226. package/src/repository/chatter-message-details.repository.ts +4 -3
  227. package/src/repository/chatter-message.repository.ts +4 -4
  228. package/src/repository/solid-base.repository.ts +2 -2
  229. package/src/seeders/module-test-data.service.ts +1 -1
  230. package/src/seeders/seed-data/solid-core-metadata.json +27 -58
  231. package/src/services/api-key.service.ts +77 -35
  232. package/src/services/authentication.service.ts +1717 -1278
  233. package/src/services/chatter-message.service.ts +22 -4
  234. package/src/services/computed-fields/entity/sequence-num-computed-field-provider.ts +1 -2
  235. package/src/services/crud-helper.service.ts +1 -4
  236. package/src/services/export-transaction.service.ts +3 -4
  237. package/src/services/field-metadata.service.ts +1 -4
  238. package/src/services/fixtures.service.ts +1 -1
  239. package/src/services/genai/mcp-handlers/mcp-handler-factory.service.ts +1 -2
  240. package/src/services/import-transaction.service.ts +1 -1
  241. package/src/services/menu-item-metadata.service.ts +2 -2
  242. package/src/services/model-metadata.service.ts +11 -13
  243. package/src/services/module-metadata.service.ts +1 -2
  244. package/src/services/queues/publisher-factory.service.ts +1 -2
  245. package/src/services/selection-providers/pseudo-foreign-key-selection-provider.service.ts +1 -1
  246. package/src/services/setting.service.ts +64 -8
  247. package/src/services/settings/default-settings-provider.service.ts +1104 -155
  248. package/src/services/solid-introspect.service.ts +1 -1
  249. package/src/services/user.service.ts +87 -0
  250. package/src/services/view-metadata.service.ts +1 -5
  251. package/src/solid-core.module.ts +25 -8
  252. package/src/subscribers/computed-entity-field.subscriber.ts +6 -6
  253. package/.claude/settings.local.json +0 -15
  254. package/src/services/1.js +0 -6
@@ -1 +1 @@
1
- {"version":3,"file":"chatter-message-details.repository.js","sourceRoot":"","sources":["../../src/repository/chatter-message-details.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,qCAIiB;AACjB,oEAA4E;AAE5E,+FAAoF;AAEpF,iFAA6E;AAC7E,yEAAoE;AACpE,mEAA8D;AAC9D,mCAA0B;AAInB,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,2CAA0C;IAC7F,YACW,UAAsB,EACtB,qBAA4C,EAC5C,sBAA8C;QAEvD,KAAK,CAAC,sDAAqB,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,CAAC;QAJ/E,eAAU,GAAV,UAAU,CAAY;QACtB,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,2BAAsB,GAAtB,sBAAsB,CAAwB;QAItC,uBAAkB,GAAG,wCAAwC,CAAC;IADjF,CAAC;IASQ,KAAK,CAAC,mCAAmC,CAChD,KAAK,GAAG,QAAQ,EAChB,WAAyB;QAEzB,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;QAC9D,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,mCAAmC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAG3B,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAClE,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QAG5B,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,KAAK,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;QAC9D,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;QAI7D,OAAO,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,CACnD,EAAE,EACF,WAAW,EACX,UAA4B,EAC5B,YAAY,CACb,CAAC;IACJ,CAAC;IAgBD,eAAe,CACb,EAAyB,EACzB,WAAmB,EACnB,eAAuB,SAAS;QAGhC,MAAM,UAAU,GAAG,IAAA,kBAAQ,EAAC,WAAW,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAErD,MAAM,OAAO,GAAG,IAAA,kBAAQ,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAKpC,EAAE,CAAC,QAAQ,CACT,UAAU,EACV,OAAO,EACP,IAAI,OAAO,aAAa,YAAY,+BAA+B,YAAY,4BAA4B,EAC3G,EAAE,KAAK,EAAE,WAAW,EAAE,CACvB,CAAC;QAEF,OAAO,EAAE,CAAC;IACZ,CAAC;IAGO,sBAAsB;QAC5B,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QACpE,IAAI,CAAC,aAAa;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAElD,MAAM,WAAW,GAAG,IAAA,YAAG,EAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChE,IAAI,CAAC,WAAW;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAEhD,MAAM,KAAK,GAAG,IAAA,kBAAQ,EAAC,WAAW,CAAC,CAAC;QACpC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;CAEF,CAAA;AA5FY,0EAA+B;0CAA/B,+BAA+B;IAD3C,IAAA,mBAAU,GAAE;qCAGY,oBAAU;QACC,+CAAqB;QACpB,iDAAsB;GAJ9C,+BAA+B,CA4F3C","sourcesContent":["import { Injectable } from '@nestjs/common';\nimport {\n DataSource,\n QueryRunner,\n SelectQueryBuilder,\n} from 'typeorm';\nimport { camelize, classify } from '@angular-devkit/core/src/utils/strings';\n\nimport { ChatterMessageDetails } from 'src/entities/chatter-message-details.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport { SecurityRuleRepository } from './security-rule.repository';\nimport { SolidBaseRepository } from './solid-base.repository';\nimport {get} from \"lodash\"\n\n\n@Injectable()\nexport class ChatterMessageDetailsRepository extends SolidBaseRepository<ChatterMessageDetails> {\n constructor(\n readonly dataSource: DataSource,\n readonly requestContextService: RequestContextService,\n readonly securityRuleRepository: SecurityRuleRepository,\n ) {\n super(ChatterMessageDetails, dataSource, requestContextService, securityRuleRepository);\n }\n private readonly CO_MODEL_NAME_PATH = 'filters.chatterMessage.coModelName.$eq';\n\n /**\n * Build a security-aware QB:\n * - join the real relation to ChatterMessage (alias: \"message\")\n * - left join the polymorphic co-model table using message.co_model_* fields\n * - (optionally) apply security rules on the co-model alias\n */\n override async createSecurityRuleAwareQueryBuilder(\n alias = 'detail',\n queryRunner?: QueryRunner,\n ): Promise<SelectQueryBuilder<ChatterMessageDetails>> {\n const activeUser = this.requestContextService.getActiveUser();\n let qb = await super.createSecurityRuleAwareQueryBuilder(alias, queryRunner);\n if (!activeUser) return qb;\n\n // Example: join the \"client\" co-model (pass whatever co-model name you need)\n const [coModelName, coModelAlias] = this.getCoModelNameAndAlias();\n if (!coModelName) return qb;\n\n // Join the real relation so we can access co_model_* fields\n qb = qb.leftJoin(`${alias}.chatterMessage`, 'chatterMessage');\n qb = this.leftJoinCoModel(qb, coModelName, 'chatterMessage');\n\n // If your security rules should apply to the co-model rows, pass the co-model alias.\n // Here we use the co-model name \"client\" both as model key and alias base for consistency.\n return this.securityRuleRepository.applySecurityRules(\n qb,\n coModelName, // modelSingularName (or whatever your rules expect)\n activeUser as ActiveUserData,\n coModelAlias, // the alias we used inside leftJoinCoModel\n );\n }\n\n /**\n * Left-join the polymorphic co-model table, matching:\n * <coModelAlias>.id = <messageAlias>.co_model_entity_id\n * AND <messageAlias>.co_model_name = :model\n *\n * @param qb QB built on ChatterMessageDetails\n * @param coModelName e.g. \"client\" | \"invoice\" | ...\n * @param messageAlias alias used for joined ChatterMessage (default: \"message\")\n *\n * Notes:\n * - We resolve the entity metadata from the classified name (e.g., \"Client\"),\n * then use metadata.tablePath to get schema-qualified table.\n * - We build a stable alias from metadata.name (camelized).\n */\n leftJoinCoModel<T>(\n qb: SelectQueryBuilder<T>,\n coModelName: string,\n messageAlias: string = 'message',\n ): SelectQueryBuilder<T> {\n // Resolve entity metadata from your naming convention\n const entityName = classify(coModelName); // \"client\" -> \"Client\"\n const meta = this.dataSource.getMetadata(entityName); // throws if not registered\n // const table = meta.tablePath; // schema-qualified\n const coAlias = camelize(meta.name); // stable alias, e.g., \"client\"\n\n // LEFT JOIN \"<schema>\".\"<table>\" \"<coAlias>\"\n // ON \"<coAlias>\".\"id\" = \"message\".\"co_model_entity_id\"\n // AND \"message\".\"co_model_name\" = :model\n qb.leftJoin(\n entityName,\n coAlias,\n `\"${coAlias}\".\"id\" = \"${messageAlias}\".\"co_model_entity_id\" AND \"${messageAlias}\".\"co_model_name\" = :model`,\n { model: coModelName },\n );\n\n return qb;\n }\n\n // This uses the requestContextService.getRequestFilter method and extracts the coModelName and creates the alias and returns the name and alias tuple\n private getCoModelNameAndAlias() {\n const requestFilter = this.requestContextService.getRequestFilter();\n if (!requestFilter) return [undefined, undefined];\n\n const coModelName = get(requestFilter, this.CO_MODEL_NAME_PATH);\n if (!coModelName) return [undefined, undefined];\n\n const alias = camelize(coModelName);\n return [coModelName, alias];\n }\n\n}"]}
1
+ {"version":3,"file":"chatter-message-details.repository.js","sourceRoot":"","sources":["../../src/repository/chatter-message-details.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,qCAIiB;AACjB,mCAA+C;AAC/C,4DAAoD;AAEpD,+FAAoF;AAEpF,iFAA6E;AAC7E,yEAAoE;AACpE,mEAA8D;AAC9D,mCAA0B;AAInB,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,2CAA0C;IAC7F,YACW,UAAsB,EACtB,qBAA4C,EAC5C,sBAA8C;QAEvD,KAAK,CAAC,sDAAqB,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,CAAC;QAJ/E,eAAU,GAAV,UAAU,CAAY;QACtB,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,2BAAsB,GAAtB,sBAAsB,CAAwB;QAItC,uBAAkB,GAAG,wCAAwC,CAAC;IADjF,CAAC;IASQ,KAAK,CAAC,mCAAmC,CAChD,KAAK,GAAG,QAAQ,EAChB,WAAyB;QAEzB,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;QAC9D,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,mCAAmC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU;YAAE,OAAO,EAAE,CAAC;QAG3B,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAClE,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QAG5B,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,KAAK,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;QAC9D,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;QAI7D,OAAO,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,CACnD,EAAE,EACF,WAAW,EACX,UAA4B,EAC5B,YAAY,CACb,CAAC;IACJ,CAAC;IAgBD,eAAe,CACb,EAAyB,EACzB,WAAmB,EACnB,eAAuB,SAAS;QAGhC,MAAM,UAAU,GAAG,IAAA,wBAAQ,EAAC,WAAW,CAAC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAErD,MAAM,OAAO,GAAG,IAAA,kBAAS,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAKrC,EAAE,CAAC,QAAQ,CACT,UAAU,EACV,OAAO,EACP,IAAI,OAAO,aAAa,YAAY,+BAA+B,YAAY,4BAA4B,EAC3G,EAAE,KAAK,EAAE,WAAW,EAAE,CACvB,CAAC;QAEF,OAAO,EAAE,CAAC;IACZ,CAAC;IAGO,sBAAsB;QAC5B,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QACpE,IAAI,CAAC,aAAa;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAElD,MAAM,WAAW,GAAG,IAAA,YAAG,EAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChE,IAAI,CAAC,WAAW;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAEhD,MAAM,KAAK,GAAG,IAAA,kBAAS,EAAC,WAAW,CAAC,CAAC;QACrC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;CAEF,CAAA;AA5FY,0EAA+B;0CAA/B,+BAA+B;IAD3C,IAAA,mBAAU,GAAE;qCAGY,oBAAU;QACC,+CAAqB;QACpB,iDAAsB;GAJ9C,+BAA+B,CA4F3C","sourcesContent":["import { Injectable } from '@nestjs/common';\nimport {\n DataSource,\n QueryRunner,\n SelectQueryBuilder,\n} from 'typeorm';\nimport { upperFirst, camelCase } from 'lodash';\nimport { classify } from '../helpers/string.helper';\n\nimport { ChatterMessageDetails } from 'src/entities/chatter-message-details.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport { SecurityRuleRepository } from './security-rule.repository';\nimport { SolidBaseRepository } from './solid-base.repository';\nimport {get} from \"lodash\"\n\n\n@Injectable()\nexport class ChatterMessageDetailsRepository extends SolidBaseRepository<ChatterMessageDetails> {\n constructor(\n readonly dataSource: DataSource,\n readonly requestContextService: RequestContextService,\n readonly securityRuleRepository: SecurityRuleRepository,\n ) {\n super(ChatterMessageDetails, dataSource, requestContextService, securityRuleRepository);\n }\n private readonly CO_MODEL_NAME_PATH = 'filters.chatterMessage.coModelName.$eq';\n\n /**\n * Build a security-aware QB:\n * - join the real relation to ChatterMessage (alias: \"message\")\n * - left join the polymorphic co-model table using message.co_model_* fields\n * - (optionally) apply security rules on the co-model alias\n */\n override async createSecurityRuleAwareQueryBuilder(\n alias = 'detail',\n queryRunner?: QueryRunner,\n ): Promise<SelectQueryBuilder<ChatterMessageDetails>> {\n const activeUser = this.requestContextService.getActiveUser();\n let qb = await super.createSecurityRuleAwareQueryBuilder(alias, queryRunner);\n if (!activeUser) return qb;\n\n // Example: join the \"client\" co-model (pass whatever co-model name you need)\n const [coModelName, coModelAlias] = this.getCoModelNameAndAlias();\n if (!coModelName) return qb;\n\n // Join the real relation so we can access co_model_* fields\n qb = qb.leftJoin(`${alias}.chatterMessage`, 'chatterMessage');\n qb = this.leftJoinCoModel(qb, coModelName, 'chatterMessage');\n\n // If your security rules should apply to the co-model rows, pass the co-model alias.\n // Here we use the co-model name \"client\" both as model key and alias base for consistency.\n return this.securityRuleRepository.applySecurityRules(\n qb,\n coModelName, // modelSingularName (or whatever your rules expect)\n activeUser as ActiveUserData,\n coModelAlias, // the alias we used inside leftJoinCoModel\n );\n }\n\n /**\n * Left-join the polymorphic co-model table, matching:\n * <coModelAlias>.id = <messageAlias>.co_model_entity_id\n * AND <messageAlias>.co_model_name = :model\n *\n * @param qb QB built on ChatterMessageDetails\n * @param coModelName e.g. \"client\" | \"invoice\" | ...\n * @param messageAlias alias used for joined ChatterMessage (default: \"message\")\n *\n * Notes:\n * - We resolve the entity metadata from the classified name (e.g., \"Client\"),\n * then use metadata.tablePath to get schema-qualified table.\n * - We build a stable alias from metadata.name (camelized).\n */\n leftJoinCoModel<T>(\n qb: SelectQueryBuilder<T>,\n coModelName: string,\n messageAlias: string = 'message',\n ): SelectQueryBuilder<T> {\n // Resolve entity metadata from your naming convention\n const entityName = classify(coModelName); // \"client\" -> \"Client\"\n const meta = this.dataSource.getMetadata(entityName); // throws if not registered\n // const table = meta.tablePath; // schema-qualified\n const coAlias = camelCase(meta.name); // stable alias, e.g., \"client\"\n\n // LEFT JOIN \"<schema>\".\"<table>\" \"<coAlias>\"\n // ON \"<coAlias>\".\"id\" = \"message\".\"co_model_entity_id\"\n // AND \"message\".\"co_model_name\" = :model\n qb.leftJoin(\n entityName,\n coAlias,\n `\"${coAlias}\".\"id\" = \"${messageAlias}\".\"co_model_entity_id\" AND \"${messageAlias}\".\"co_model_name\" = :model`,\n { model: coModelName },\n );\n\n return qb;\n }\n\n // This uses the requestContextService.getRequestFilter method and extracts the coModelName and creates the alias and returns the name and alias tuple\n private getCoModelNameAndAlias() {\n const requestFilter = this.requestContextService.getRequestFilter();\n if (!requestFilter) return [undefined, undefined];\n\n const coModelName = get(requestFilter, this.CO_MODEL_NAME_PATH);\n if (!coModelName) return [undefined, undefined];\n\n const alias = camelCase(coModelName);\n return [coModelName, alias];\n }\n\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"chatter-message.repository.d.ts","sourceRoot":"","sources":["../../src/repository/chatter-message.repository.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAErE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAG9D,qBACa,wBAAyB,SAAQ,mBAAmB,CAAC,cAAc,CAAC;IAEzE,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IACrD,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;gBAF9C,UAAU,EAAE,UAAU,EACtB,qBAAqB,EAAE,qBAAqB,EAC5C,sBAAsB,EAAE,sBAAsB;IAK3D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IACjD,mCAAmC,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAkB1I,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,sBAAsB;CAUjC"}
1
+ {"version":3,"file":"chatter-message.repository.d.ts","sourceRoot":"","sources":["../../src/repository/chatter-message.repository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAErE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAI9D,qBACa,wBAAyB,SAAQ,mBAAmB,CAAC,cAAc,CAAC;IAEzE,QAAQ,CAAC,UAAU,EAAE,UAAU;IAC/B,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB;IACrD,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB;gBAF9C,UAAU,EAAE,UAAU,EACtB,qBAAqB,EAAE,qBAAqB,EAC5C,sBAAsB,EAAE,sBAAsB;IAK3D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IACjD,mCAAmC,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;IAkB1I,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,sBAAsB;CAUjC"}
@@ -10,7 +10,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.ChatterMessageRepository = void 0;
13
- const strings_1 = require("@angular-devkit/core/src/utils/strings");
14
13
  const common_1 = require("@nestjs/common");
15
14
  const chatter_message_entity_1 = require("../entities/chatter-message.entity");
16
15
  const request_context_service_1 = require("../services/request-context.service");
@@ -18,6 +17,7 @@ const typeorm_1 = require("typeorm");
18
17
  const security_rule_repository_1 = require("./security-rule.repository");
19
18
  const solid_base_repository_1 = require("./solid-base.repository");
20
19
  const lodash_1 = require("lodash");
20
+ const string_helper_1 = require("../helpers/string.helper");
21
21
  let ChatterMessageRepository = class ChatterMessageRepository extends solid_base_repository_1.SolidBaseRepository {
22
22
  constructor(dataSource, requestContextService, securityRuleRepository) {
23
23
  super(chatter_message_entity_1.ChatterMessage, dataSource, requestContextService, securityRuleRepository);
@@ -38,9 +38,9 @@ let ChatterMessageRepository = class ChatterMessageRepository extends solid_base
38
38
  return this.securityRuleRepository.applySecurityRules(qb, coModelName, activeUserOrUndefined, coModelAlias);
39
39
  }
40
40
  leftJoinCoModel(qb, coModelName) {
41
- const entityName = (0, strings_1.classify)(coModelName);
41
+ const entityName = (0, string_helper_1.classify)(coModelName);
42
42
  const meta = this.dataSource.getMetadata(entityName);
43
- const alias = (0, strings_1.camelize)(meta.name);
43
+ const alias = (0, lodash_1.camelCase)(meta.name);
44
44
  qb.leftJoin(entityName, alias, `${alias}.id = entity.co_model_entity_id AND entity.co_model_name = :model`, { model: coModelName });
45
45
  return qb;
46
46
  }
@@ -51,7 +51,7 @@ let ChatterMessageRepository = class ChatterMessageRepository extends solid_base
51
51
  const coModelName = (0, lodash_1.get)(requestFilter, this.CO_MODEL_NAME_PATH);
52
52
  if (!coModelName)
53
53
  return [undefined, undefined];
54
- const alias = (0, strings_1.camelize)(coModelName);
54
+ const alias = (0, lodash_1.camelCase)(coModelName);
55
55
  return [coModelName, alias];
56
56
  }
57
57
  };
@@ -1 +1 @@
1
- {"version":3,"file":"chatter-message.repository.js","sourceRoot":"","sources":["../../src/repository/chatter-message.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oEAA4E;AAC5E,2CAA4C;AAC5C,+EAAqE;AAErE,iFAA6E;AAC7E,qCAAsE;AACtE,yEAAoE;AACpE,mEAA8D;AAC9D,mCAA0B;AAGnB,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,2CAAmC;IAC7E,YACa,UAAsB,EACtB,qBAA4C,EAC5C,sBAA8C;QAEvD,KAAK,CAAC,uCAAc,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,CAAC;QAJxE,eAAU,GAAV,UAAU,CAAY;QACtB,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,2BAAsB,GAAtB,sBAAsB,CAAwB;QAK1C,uBAAkB,GAAG,yBAAyB,CAAC;IAFhE,CAAC;IAGQ,KAAK,CAAC,mCAAmC,CAAC,KAAc,EAAE,WAAyB;QACxF,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;QACzE,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,mCAAmC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC7E,IAAI,CAAC,qBAAqB;YAAE,OAAO,EAAE,CAAC;QAGtC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAClE,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QAC5B,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAE3C,OAAO,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,CACjD,EAAE,EACF,WAAW,EACX,qBAAuC,EACvC,YAAY,CACf,CAAC;IACN,CAAC;IAEO,eAAe,CACnB,EAAsC,EACtC,WAAmB;QAGnB,MAAM,UAAU,GAAG,IAAA,kBAAQ,EAAC,WAAW,CAAC,CAAA;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,IAAA,kBAAQ,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,EAAE,CAAC,QAAQ,CACP,UAAU,EACV,KAAK,EAEL,GAAG,KAAK,mEAAmE,EAC3E,EAAE,KAAK,EAAE,WAAW,EAAE,CACzB,CAAC;QACF,OAAO,EAAE,CAAC;IAEd,CAAC;IAGO,sBAAsB;QAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QACpE,IAAI,CAAC,aAAa;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAElD,MAAM,WAAW,GAAG,IAAA,YAAG,EAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChE,IAAI,CAAC,WAAW;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAA,kBAAQ,EAAC,WAAW,CAAC,CAAC;QACpC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;CAEJ,CAAA;AA1DY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;qCAGgB,oBAAU;QACC,+CAAqB;QACpB,iDAAsB;GAJlD,wBAAwB,CA0DpC","sourcesContent":["import { camelize, classify } from \"@angular-devkit/core/src/utils/strings\";\nimport { Injectable } from \"@nestjs/common\";\nimport { ChatterMessage } from \"src/entities/chatter-message.entity\";\nimport { ActiveUserData } from \"src/interfaces/active-user-data.interface\";\nimport { RequestContextService } from \"src/services/request-context.service\";\nimport { DataSource, QueryRunner, SelectQueryBuilder } from \"typeorm\";\nimport { SecurityRuleRepository } from \"./security-rule.repository\";\nimport { SolidBaseRepository } from \"./solid-base.repository\";\nimport {get} from \"lodash\"\n\n@Injectable()\nexport class ChatterMessageRepository extends SolidBaseRepository<ChatterMessage> {\n constructor(\n readonly dataSource: DataSource,\n readonly requestContextService: RequestContextService,\n readonly securityRuleRepository: SecurityRuleRepository,\n ) {\n super(ChatterMessage, dataSource, requestContextService, securityRuleRepository);\n }\n\n private readonly CO_MODEL_NAME_PATH = 'filters.coModelName.$eq';\n override async createSecurityRuleAwareQueryBuilder(alias?: string, queryRunner?: QueryRunner): Promise<SelectQueryBuilder<ChatterMessage>> {\n const activeUserOrUndefined = this.requestContextService.getActiveUser();\n let qb = await super.createSecurityRuleAwareQueryBuilder(alias, queryRunner);\n if (!activeUserOrUndefined) return qb;\n \n //Left join on the associated chatter model entity\n const [coModelName, coModelAlias] = this.getCoModelNameAndAlias();\n if (!coModelName) return qb;\n qb = this.leftJoinCoModel(qb, coModelName);\n \n return this.securityRuleRepository.applySecurityRules(\n qb,\n coModelName,\n activeUserOrUndefined as ActiveUserData,\n coModelAlias\n );\n }\n\n private leftJoinCoModel<ChatterMessage>(\n qb: SelectQueryBuilder<ChatterMessage>,\n coModelName: string\n ) {\n // const Target = resolveEntityFromCoModelName(coModelName); // your mapping\n const entityName = classify(coModelName)\n const meta = this.dataSource.getMetadata(entityName);\n const alias = camelize(meta.name);\n qb.leftJoin(\n entityName,\n alias,\n // `${alias}.id = entity.co_model_entity_id`,\n `${alias}.id = entity.co_model_entity_id AND entity.co_model_name = :model`,\n { model: coModelName }\n );\n return qb;\n // return qb.leftJoin(Target, alias, `${alias}.id = entity.co_model_entity_id`);\n }\n\n // This uses the requestContextService.getRequestFilter method and extracts the coModelName and creates the alias and returns the name and alias tuple\n private getCoModelNameAndAlias() {\n const requestFilter = this.requestContextService.getRequestFilter();\n if (!requestFilter) return [undefined, undefined];\n\n const coModelName = get(requestFilter, this.CO_MODEL_NAME_PATH);\n if (!coModelName) return [undefined, undefined];\n const alias = camelize(coModelName);\n return [coModelName, alias];\n }\n\n}"]}
1
+ {"version":3,"file":"chatter-message.repository.js","sourceRoot":"","sources":["../../src/repository/chatter-message.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,+EAAqE;AAErE,iFAA6E;AAC7E,qCAAsE;AACtE,yEAAoE;AACpE,mEAA8D;AAC9D,mCAAwC;AACxC,4DAAoD;AAG7C,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,2CAAmC;IAC7E,YACa,UAAsB,EACtB,qBAA4C,EAC5C,sBAA8C;QAEvD,KAAK,CAAC,uCAAc,EAAE,UAAU,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,CAAC;QAJxE,eAAU,GAAV,UAAU,CAAY;QACtB,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,2BAAsB,GAAtB,sBAAsB,CAAwB;QAK1C,uBAAkB,GAAG,yBAAyB,CAAC;IAFhE,CAAC;IAGQ,KAAK,CAAC,mCAAmC,CAAC,KAAc,EAAE,WAAyB;QACxF,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;QACzE,IAAI,EAAE,GAAG,MAAM,KAAK,CAAC,mCAAmC,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC7E,IAAI,CAAC,qBAAqB;YAAE,OAAO,EAAE,CAAC;QAGtC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAClE,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QAC5B,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAE3C,OAAO,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,CACjD,EAAE,EACF,WAAW,EACX,qBAAuC,EACvC,YAAY,CACf,CAAC;IACN,CAAC;IAEO,eAAe,CACnB,EAAsC,EACtC,WAAmB;QAGnB,MAAM,UAAU,GAAG,IAAA,wBAAQ,EAAC,WAAW,CAAC,CAAA;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,IAAA,kBAAS,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,EAAE,CAAC,QAAQ,CACP,UAAU,EACV,KAAK,EAEL,GAAG,KAAK,mEAAmE,EAC3E,EAAE,KAAK,EAAE,WAAW,EAAE,CACzB,CAAC;QACF,OAAO,EAAE,CAAC;IAEd,CAAC;IAGO,sBAAsB;QAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QACpE,IAAI,CAAC,aAAa;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAElD,MAAM,WAAW,GAAG,IAAA,YAAG,EAAC,aAAa,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAChE,IAAI,CAAC,WAAW;YAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAA,kBAAS,EAAC,WAAW,CAAC,CAAC;QACrC,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAChC,CAAC;CAEJ,CAAA;AA1DY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;qCAGgB,oBAAU;QACC,+CAAqB;QACpB,iDAAsB;GAJlD,wBAAwB,CA0DpC","sourcesContent":["import { Injectable } from \"@nestjs/common\";\nimport { ChatterMessage } from \"src/entities/chatter-message.entity\";\nimport { ActiveUserData } from \"src/interfaces/active-user-data.interface\";\nimport { RequestContextService } from \"src/services/request-context.service\";\nimport { DataSource, QueryRunner, SelectQueryBuilder } from \"typeorm\";\nimport { SecurityRuleRepository } from \"./security-rule.repository\";\nimport { SolidBaseRepository } from \"./solid-base.repository\";\nimport { get, camelCase } from 'lodash';\nimport { classify } from '../helpers/string.helper';\n\n@Injectable()\nexport class ChatterMessageRepository extends SolidBaseRepository<ChatterMessage> {\n constructor(\n readonly dataSource: DataSource,\n readonly requestContextService: RequestContextService,\n readonly securityRuleRepository: SecurityRuleRepository,\n ) {\n super(ChatterMessage, dataSource, requestContextService, securityRuleRepository);\n }\n\n private readonly CO_MODEL_NAME_PATH = 'filters.coModelName.$eq';\n override async createSecurityRuleAwareQueryBuilder(alias?: string, queryRunner?: QueryRunner): Promise<SelectQueryBuilder<ChatterMessage>> {\n const activeUserOrUndefined = this.requestContextService.getActiveUser();\n let qb = await super.createSecurityRuleAwareQueryBuilder(alias, queryRunner);\n if (!activeUserOrUndefined) return qb;\n \n //Left join on the associated chatter model entity\n const [coModelName, coModelAlias] = this.getCoModelNameAndAlias();\n if (!coModelName) return qb;\n qb = this.leftJoinCoModel(qb, coModelName);\n \n return this.securityRuleRepository.applySecurityRules(\n qb,\n coModelName,\n activeUserOrUndefined as ActiveUserData,\n coModelAlias\n );\n }\n\n private leftJoinCoModel<ChatterMessage>(\n qb: SelectQueryBuilder<ChatterMessage>,\n coModelName: string\n ) {\n // const Target = resolveEntityFromCoModelName(coModelName); // your mapping\n const entityName = classify(coModelName)\n const meta = this.dataSource.getMetadata(entityName);\n const alias = camelCase(meta.name);\n qb.leftJoin(\n entityName,\n alias,\n // `${alias}.id = entity.co_model_entity_id`,\n `${alias}.id = entity.co_model_entity_id AND entity.co_model_name = :model`,\n { model: coModelName }\n );\n return qb;\n // return qb.leftJoin(Target, alias, `${alias}.id = entity.co_model_entity_id`);\n }\n\n // This uses the requestContextService.getRequestFilter method and extracts the coModelName and creates the alias and returns the name and alias tuple\n private getCoModelNameAndAlias() {\n const requestFilter = this.requestContextService.getRequestFilter();\n if (!requestFilter) return [undefined, undefined];\n\n const coModelName = get(requestFilter, this.CO_MODEL_NAME_PATH);\n if (!coModelName) return [undefined, undefined];\n const alias = camelCase(coModelName);\n return [coModelName, alias];\n }\n\n}"]}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SolidBaseRepository = void 0;
4
- const strings_1 = require("@angular-devkit/core/src/utils/strings");
4
+ const lodash_1 = require("lodash");
5
5
  const common_1 = require("@nestjs/common");
6
6
  const model_metadata_entity_1 = require("../entities/model-metadata.entity");
7
7
  const typeorm_1 = require("typeorm");
@@ -13,7 +13,7 @@ class SolidBaseRepository extends typeorm_1.Repository {
13
13
  this.logger = new common_1.Logger(this.constructor.name);
14
14
  }
15
15
  modelSingularName() {
16
- return (0, strings_1.camelize)(this.metadata.name);
16
+ return (0, lodash_1.camelCase)(this.metadata.name);
17
17
  }
18
18
  async findOneByUserKey(userKeyValue) {
19
19
  const modelSingularName = this.modelSingularName();
@@ -1 +1 @@
1
- {"version":3,"file":"solid-base.repository.js","sourceRoot":"","sources":["../../src/repository/solid-base.repository.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelize } from '@angular-devkit/core/src/utils/strings';\nimport { Logger } from '@nestjs/common';\nimport { CommonEntity } from 'src/entities/common.entity';\nimport { ModelMetadata } from 'src/entities/model-metadata.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport {\n DataSource,\n EntityNotFoundError,\n EntityTarget,\n FindManyOptions,\n FindOneOptions,\n FindOptionsWhere,\n QueryRunner,\n Repository,\n SelectQueryBuilder,\n UpdateResult\n} from 'typeorm';\nimport { SecurityRuleRepository } from './security-rule.repository';\nimport { PickKeysByType } from 'typeorm/common/PickKeysByType';\n\nexport class SolidBaseRepository<T extends CommonEntity> extends Repository<T> {\n protected readonly logger: Logger;\n\n constructor(\n entity: EntityTarget<T>,\n dataSource: DataSource,\n protected readonly requestContextService: RequestContextService | null,\n protected readonly securityRuleRepository: SecurityRuleRepository | null,\n ) {\n super(entity, dataSource.createEntityManager());\n this.logger = new Logger(this.constructor.name);\n }\n\n modelSingularName(): string {\n return camelize(this.metadata.name);\n }\n\n async findOneByUserKey(userKeyValue: string | number): Promise<T | null> {\n const modelSingularName = this.modelSingularName();\n const modelMetaRepo = this.manager.getRepository(ModelMetadata);\n const modelMeta = await modelMetaRepo.findOne({\n where: { singularName: modelSingularName },\n relations: { userKeyField: true },\n });\n\n if (!modelMeta?.userKeyField?.name) {\n throw new Error(`User key field not found for model ${modelSingularName}`);\n }\n\n return this.findOneBy({ [modelMeta.userKeyField.name]: userKeyValue } as FindOptionsWhere<T>);\n }\n\n override createQueryBuilder(alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder<T> {\n throw new Error('createQueryBuilder() is disabled. Use createSecurityRuleAwareQueryBuilder instead');\n }\n\n async createSecurityRuleAwareQueryBuilder(alias?: string, queryRunner?: QueryRunner): Promise<SelectQueryBuilder<T>> {\n const qb = super.createQueryBuilder(alias, queryRunner);\n\n if (!this.securityRuleRepository) return qb;\n if (!this.requestContextService) return qb;\n\n const activeUserOrUndefined = this.requestContextService.getActiveUser();\n if (!activeUserOrUndefined) return qb;\n\n return await this.securityRuleRepository.applySecurityRules(\n qb,\n this.modelSingularName(),\n activeUserOrUndefined as ActiveUserData\n );\n }\n\n /**\n * Security-aware findOne: applies FindOneOptions via FindOptionsUtils,\n * but builds from our security-wrapped QueryBuilder.\n */\n override async findOne(options?: FindOneOptions<T>): Promise<T | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n // Apply all standard find options (relations, selects, order, where, etc.)\n if (options) qb.setFindOptions(options); // <- applies where, relations, select, order, etc.\n }\n\n return qb.getOne();\n }\n\n /**\n * Convenience: route findOneBy through the same path so rules apply.\n */\n override async findOneBy(where: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<T | null> {\n return this.findOne({ where });\n }\n\n /**\n * Optional: an OrFail that still honors security rules.\n */\n override async findOneOrFail(options?: FindOneOptions<T>): Promise<T> {\n const entity = await this.findOne(options);\n if (!entity) {\n throw new EntityNotFoundError(this.metadata.target, options?.where ?? {});\n }\n return entity;\n }\n\n /**\n * Security-aware find(): builds from our secured QB and preserves all FindManyOptions\n * (where, relations, select, order, take/skip, withDeleted, etc.).\n */\n override async find(options?: FindManyOptions<T>): Promise<T[]> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n qb.setFindOptions(options);\n }\n\n return qb.getMany();\n }\n\n /**\n * (Optional) Security-aware findAndCount(): same as find(), plus a total count.\n * Mirrors Repository.findAndCount semantics.\n */\n override async findAndCount(options?: FindManyOptions<T>): Promise<[T[], number]> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n qb.setFindOptions(options);\n }\n\n return qb.getManyAndCount();\n }\n\n /**\n * Security-aware count(): applies security rules before counting.\n */\n override async count(options?: FindManyOptions<T>): Promise<number> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n qb.setFindOptions(options);\n }\n\n return qb.getCount();\n }\n\n /**\n * Security-aware countBy(): convenience wrapper routed through count().\n */\n override async countBy(where: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number> {\n return this.count({ where });\n }\n\n /**\n * Security-aware average(): applies security rules before computing the average.\n */\n override async average(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`AVG(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'avg')\n .getRawOne<{ avg: string | number | null }>();\n\n if (result?.avg === null || result?.avg === undefined) {\n return null;\n }\n\n return typeof result.avg === 'number'\n ? result.avg\n : parseFloat(result.avg);\n }\n\n /**\n * Security-aware sum(): applies security rules before computing the sum.\n */\n override async sum(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`SUM(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'sum')\n .getRawOne<{ sum: string | number | null }>();\n\n if (result?.sum === null || result?.sum === undefined) {\n return null;\n }\n\n return typeof result.sum === 'number'\n ? result.sum\n : parseFloat(result.sum);\n }\n\n /**\n * Security-aware minimum(): applies security rules before computing the minimum.\n */\n override async minimum(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`MIN(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'min')\n .getRawOne<{ min: string | number | null }>();\n\n if (result?.min === null || result?.min === undefined) {\n return null;\n }\n\n return typeof result.min === 'number'\n ? result.min\n : parseFloat(result.min);\n }\n\n /**\n * Security-aware maximum(): applies security rules before computing the maximum.\n */\n override async maximum(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`MAX(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'max')\n .getRawOne<{ max: string | number | null }>();\n\n if (result?.max === null || result?.max === undefined) {\n return null;\n }\n\n return typeof result.max === 'number'\n ? result.max\n : parseFloat(result.max);\n }\n\n /**\n * Security-aware increment(): increments a column by a given value for all matching rows.\n * Security rules are applied to determine which rows the user is allowed to modify.\n */\n override async increment(where: FindOptionsWhere<T>, propertyPath: string, value: string | number,): Promise<UpdateResult> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n qb.setFindOptions({ where });\n\n const rows = await qb.select(`${alias}.id`).getMany();\n const ids = rows.map((r) => (r as any).id);\n\n if (ids.length === 0) {\n return { raw: [], affected: 0, generatedMaps: [] };\n }\n\n return this.manager\n .createQueryBuilder()\n .update(this.metadata.target)\n .set({ [propertyPath]: () => `${propertyPath} + :value` } as any)\n .whereInIds(ids)\n .setParameter('value', value)\n .execute();\n }\n\n /**\n * Security-aware decrement(): decrements a column by a given value for all matching rows.\n * Security rules are applied to determine which rows the user is allowed to modify.\n */\n override async decrement(where: FindOptionsWhere<T>, propertyPath: string, value: string | number,): Promise<UpdateResult> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n qb.setFindOptions({ where });\n\n const rows = await qb.select(`${alias}.id`).getMany();\n const ids = rows.map((r) => (r as any).id);\n\n if (ids.length === 0) {\n return { raw: [], affected: 0, generatedMaps: [] };\n }\n\n return this.manager\n .createQueryBuilder()\n .update(this.metadata.target)\n .set({ [propertyPath]: () => `${propertyPath} - :value` } as any)\n .whereInIds(ids)\n .setParameter('value', value)\n .execute();\n }\n}\n"]}
1
+ {"version":3,"file":"solid-base.repository.js","sourceRoot":"","sources":["../../src/repository/solid-base.repository.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelCase } from 'lodash';\nimport { Logger } from '@nestjs/common';\nimport { CommonEntity } from 'src/entities/common.entity';\nimport { ModelMetadata } from 'src/entities/model-metadata.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport {\n DataSource,\n EntityNotFoundError,\n EntityTarget,\n FindManyOptions,\n FindOneOptions,\n FindOptionsWhere,\n QueryRunner,\n Repository,\n SelectQueryBuilder,\n UpdateResult\n} from 'typeorm';\nimport { SecurityRuleRepository } from './security-rule.repository';\nimport { PickKeysByType } from 'typeorm/common/PickKeysByType';\n\nexport class SolidBaseRepository<T extends CommonEntity> extends Repository<T> {\n protected readonly logger: Logger;\n\n constructor(\n entity: EntityTarget<T>,\n dataSource: DataSource,\n protected readonly requestContextService: RequestContextService | null,\n protected readonly securityRuleRepository: SecurityRuleRepository | null,\n ) {\n super(entity, dataSource.createEntityManager());\n this.logger = new Logger(this.constructor.name);\n }\n\n modelSingularName(): string {\n return camelCase(this.metadata.name);\n }\n\n async findOneByUserKey(userKeyValue: string | number): Promise<T | null> {\n const modelSingularName = this.modelSingularName();\n const modelMetaRepo = this.manager.getRepository(ModelMetadata);\n const modelMeta = await modelMetaRepo.findOne({\n where: { singularName: modelSingularName },\n relations: { userKeyField: true },\n });\n\n if (!modelMeta?.userKeyField?.name) {\n throw new Error(`User key field not found for model ${modelSingularName}`);\n }\n\n return this.findOneBy({ [modelMeta.userKeyField.name]: userKeyValue } as FindOptionsWhere<T>);\n }\n\n override createQueryBuilder(alias?: string, queryRunner?: QueryRunner): SelectQueryBuilder<T> {\n throw new Error('createQueryBuilder() is disabled. Use createSecurityRuleAwareQueryBuilder instead');\n }\n\n async createSecurityRuleAwareQueryBuilder(alias?: string, queryRunner?: QueryRunner): Promise<SelectQueryBuilder<T>> {\n const qb = super.createQueryBuilder(alias, queryRunner);\n\n if (!this.securityRuleRepository) return qb;\n if (!this.requestContextService) return qb;\n\n const activeUserOrUndefined = this.requestContextService.getActiveUser();\n if (!activeUserOrUndefined) return qb;\n\n return await this.securityRuleRepository.applySecurityRules(\n qb,\n this.modelSingularName(),\n activeUserOrUndefined as ActiveUserData\n );\n }\n\n /**\n * Security-aware findOne: applies FindOneOptions via FindOptionsUtils,\n * but builds from our security-wrapped QueryBuilder.\n */\n override async findOne(options?: FindOneOptions<T>): Promise<T | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n // Apply all standard find options (relations, selects, order, where, etc.)\n if (options) qb.setFindOptions(options); // <- applies where, relations, select, order, etc.\n }\n\n return qb.getOne();\n }\n\n /**\n * Convenience: route findOneBy through the same path so rules apply.\n */\n override async findOneBy(where: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<T | null> {\n return this.findOne({ where });\n }\n\n /**\n * Optional: an OrFail that still honors security rules.\n */\n override async findOneOrFail(options?: FindOneOptions<T>): Promise<T> {\n const entity = await this.findOne(options);\n if (!entity) {\n throw new EntityNotFoundError(this.metadata.target, options?.where ?? {});\n }\n return entity;\n }\n\n /**\n * Security-aware find(): builds from our secured QB and preserves all FindManyOptions\n * (where, relations, select, order, take/skip, withDeleted, etc.).\n */\n override async find(options?: FindManyOptions<T>): Promise<T[]> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n qb.setFindOptions(options);\n }\n\n return qb.getMany();\n }\n\n /**\n * (Optional) Security-aware findAndCount(): same as find(), plus a total count.\n * Mirrors Repository.findAndCount semantics.\n */\n override async findAndCount(options?: FindManyOptions<T>): Promise<[T[], number]> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n qb.setFindOptions(options);\n }\n\n return qb.getManyAndCount();\n }\n\n /**\n * Security-aware count(): applies security rules before counting.\n */\n override async count(options?: FindManyOptions<T>): Promise<number> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (options) {\n qb.setFindOptions(options);\n }\n\n return qb.getCount();\n }\n\n /**\n * Security-aware countBy(): convenience wrapper routed through count().\n */\n override async countBy(where: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number> {\n return this.count({ where });\n }\n\n /**\n * Security-aware average(): applies security rules before computing the average.\n */\n override async average(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`AVG(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'avg')\n .getRawOne<{ avg: string | number | null }>();\n\n if (result?.avg === null || result?.avg === undefined) {\n return null;\n }\n\n return typeof result.avg === 'number'\n ? result.avg\n : parseFloat(result.avg);\n }\n\n /**\n * Security-aware sum(): applies security rules before computing the sum.\n */\n override async sum(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`SUM(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'sum')\n .getRawOne<{ sum: string | number | null }>();\n\n if (result?.sum === null || result?.sum === undefined) {\n return null;\n }\n\n return typeof result.sum === 'number'\n ? result.sum\n : parseFloat(result.sum);\n }\n\n /**\n * Security-aware minimum(): applies security rules before computing the minimum.\n */\n override async minimum(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`MIN(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'min')\n .getRawOne<{ min: string | number | null }>();\n\n if (result?.min === null || result?.min === undefined) {\n return null;\n }\n\n return typeof result.min === 'number'\n ? result.min\n : parseFloat(result.min);\n }\n\n /**\n * Security-aware maximum(): applies security rules before computing the maximum.\n */\n override async maximum(columnName: PickKeysByType<T, number>, where?: FindOptionsWhere<T> | FindOptionsWhere<T>[]): Promise<number | null> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n if (where) {\n qb.setFindOptions({ where });\n }\n\n const result = await qb\n .select(`MAX(CAST(${alias}.${String(columnName)} AS FLOAT))`, 'max')\n .getRawOne<{ max: string | number | null }>();\n\n if (result?.max === null || result?.max === undefined) {\n return null;\n }\n\n return typeof result.max === 'number'\n ? result.max\n : parseFloat(result.max);\n }\n\n /**\n * Security-aware increment(): increments a column by a given value for all matching rows.\n * Security rules are applied to determine which rows the user is allowed to modify.\n */\n override async increment(where: FindOptionsWhere<T>, propertyPath: string, value: string | number,): Promise<UpdateResult> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n qb.setFindOptions({ where });\n\n const rows = await qb.select(`${alias}.id`).getMany();\n const ids = rows.map((r) => (r as any).id);\n\n if (ids.length === 0) {\n return { raw: [], affected: 0, generatedMaps: [] };\n }\n\n return this.manager\n .createQueryBuilder()\n .update(this.metadata.target)\n .set({ [propertyPath]: () => `${propertyPath} + :value` } as any)\n .whereInIds(ids)\n .setParameter('value', value)\n .execute();\n }\n\n /**\n * Security-aware decrement(): decrements a column by a given value for all matching rows.\n * Security rules are applied to determine which rows the user is allowed to modify.\n */\n override async decrement(where: FindOptionsWhere<T>, propertyPath: string, value: string | number,): Promise<UpdateResult> {\n const alias = this.modelSingularName();\n const qb = await this.createSecurityRuleAwareQueryBuilder(alias);\n\n qb.setFindOptions({ where });\n\n const rows = await qb.select(`${alias}.id`).getMany();\n const ids = rows.map((r) => (r as any).id);\n\n if (ids.length === 0) {\n return { raw: [], affected: 0, generatedMaps: [] };\n }\n\n return this.manager\n .createQueryBuilder()\n .update(this.metadata.target)\n .set({ [propertyPath]: () => `${propertyPath} - :value` } as any)\n .whereInIds(ids)\n .setParameter('value', value)\n .execute();\n }\n}\n"]}
@@ -50,7 +50,7 @@ exports.ModuleTestDataService = void 0;
50
50
  const common_1 = require("@nestjs/common");
51
51
  const core_1 = require("@nestjs/core");
52
52
  const typeorm_1 = require("@nestjs/typeorm");
53
- const strings_1 = require("@angular-devkit/core/src/utils/strings");
53
+ const string_helper_1 = require("../helpers/string.helper");
54
54
  const typeorm_2 = require("typeorm");
55
55
  const fs = __importStar(require("fs"));
56
56
  const path = __importStar(require("path"));
@@ -401,7 +401,7 @@ let ModuleTestDataService = ModuleTestDataService_1 = class ModuleTestDataServic
401
401
  }
402
402
  const existingRelated = await this.entityManager
403
403
  .createQueryBuilder()
404
- .relation((0, strings_1.classify)(modelUserKey), field.name)
404
+ .relation((0, string_helper_1.classify)(modelUserKey), field.name)
405
405
  .of(entityId)
406
406
  .loadMany();
407
407
  const existingIds = existingRelated.map((e) => e.id);
@@ -410,7 +410,7 @@ let ModuleTestDataService = ModuleTestDataService_1 = class ModuleTestDataServic
410
410
  if (toAdd.length > 0 || toRemove.length > 0) {
411
411
  await this.entityManager
412
412
  .createQueryBuilder()
413
- .relation((0, strings_1.classify)(modelUserKey), field.name)
413
+ .relation((0, string_helper_1.classify)(modelUserKey), field.name)
414
414
  .of(entityId)
415
415
  .addAndRemove(toAdd, toRemove);
416
416
  }
@@ -467,7 +467,7 @@ let ModuleTestDataService = ModuleTestDataService_1 = class ModuleTestDataServic
467
467
  return this.moduleRef.get(media_repository_1.MediaRepository, { strict: false });
468
468
  }
469
469
  resolveRepository(modelUserKey) {
470
- const repoName = `${(0, strings_1.classify)(modelUserKey)}Repository`;
470
+ const repoName = `${(0, string_helper_1.classify)(modelUserKey)}Repository`;
471
471
  const providers = this.discoveryService.getProviders();
472
472
  const wrapper = providers.find((provider) => provider.name === repoName);
473
473
  const repo = wrapper?.instance;
@@ -1 +1 @@
1
- {"version":3,"file":"module-test-data.service.js","sourceRoot":"","sources":["../../src/seeders/module-test-data.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { DiscoveryService, ModuleRef } from '@nestjs/core';\nimport { getDataSourceToken } from '@nestjs/typeorm';\nimport { classify } from '@angular-devkit/core/src/utils/strings';\nimport { DataSource, EntityManager } from 'typeorm';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport solidCoreMetadata from './seed-data/solid-core-metadata.json';\nimport { CreateModuleMetadataDto } from 'src/dtos/create-module-metadata.dto';\nimport { CreateModelMetadataDto } from 'src/dtos/create-model-metadata.dto';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { getDynamicModuleNamesBasedOnMetadata } from 'src/helpers/module.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { MediaRepository } from 'src/repository/media.repository';\nimport { PermissionMetadataRepository } from 'src/repository/permission-metadata.repository';\nimport { AuthenticationService } from 'src/services/authentication.service';\nimport { ModelMetadataService } from 'src/services/model-metadata.service';\nimport { RoleMetadataService } from 'src/services/role-metadata.service';\nimport { UserService } from 'src/services/user.service';\nimport { getMediaStorageProvider } from 'src/services/mediaStorageProviders';\nimport { TestingRoleSpec, TestingUserSpec } from 'src/testing/contracts/testing-metadata.types';\n\n@Injectable()\nexport class ModuleTestDataService {\n private readonly logger = new Logger(ModuleTestDataService.name);\n\n constructor(\n private readonly moduleRef: ModuleRef,\n private readonly discoveryService: DiscoveryService,\n private readonly solidRegistry: SolidRegistry,\n ) {}\n\n async setupTestData(modulesToTest?: string[]): Promise<void> {\n const testDataFiles = this.testDataFiles;\n const filteredFiles = modulesToTest?.length ? testDataFiles.filter((file) => modulesToTest.includes(file.moduleMetadata?.name)) : testDataFiles;\n\n if (filteredFiles.length === 0) {\n this.logger.warn('No modules matched the provided modulesToTest list.');\n console.log('No modules matched the provided modulesToTest list.');\n return;\n }\n\n for (const overallMetadata of filteredFiles) {\n const moduleName = overallMetadata?.moduleMetadata?.name ?? 'unknown';\n this.logger.log(`Processing test data for module: ${moduleName}`);\n console.log(`Processing test data for module: ${moduleName}`);\n await this.seedTestData(overallMetadata);\n console.log(`✔ Test data setup complete for module: ${moduleName}`);\n }\n }\n\n async createTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (fs.existsSync(manifestPath)) {\n console.log('Existing .solidx-test-manifest found; skipping test datasource creation.');\n return;\n }\n\n const dbRunName = this.generateDbRunName();\n const timestamp = this.getTimestamp();\n const envPath = path.join(process.cwd(), '.env');\n if (!fs.existsSync(envPath)) {\n throw new Error(`Base .env file not found at ${envPath}`);\n }\n\n const datasourceNames = this.solidRegistry\n .getSolidDatabaseModules()\n .map((wrapper) => wrapper.instance?.name?.())\n .filter(Boolean)\n .map((name) => name.toLowerCase()) as string[];\n\n if (datasourceNames.length === 0) {\n throw new Error('No solid database modules registered; cannot create test datasources.');\n }\n\n const dbNameByDatasource = new Map<string, string>();\n for (const dsName of datasourceNames) {\n dbNameByDatasource.set(dsName, `${dsName}_${timestamp}_${dbRunName}`);\n }\n\n const newEnvContents = this.buildTestEnvContents(\n fs.readFileSync(envPath, 'utf-8'),\n dbNameByDatasource,\n );\n\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${dbRunName}`);\n fs.copyFileSync(envPath, backupEnvPath);\n fs.writeFileSync(envPath, newEnvContents);\n console.log(`Backed up .env to ${path.basename(backupEnvPath)} and applied new test datasource names to .env.`);\n\n this.updateTestManifest(dbRunName, timestamp, dbNameByDatasource);\n\n await this.createTestDatabaseObjects(dbNameByDatasource);\n\n const dbList = Array.from(dbNameByDatasource.entries())\n .map(([dsName, dbName]) => `- ${dsName}: ${dbName}`)\n .join('\\n');\n\n const instructions = [\n '',\n '============================================================',\n ' TEST DATASOURCE ENVIRONMENT CREATED',\n '------------------------------------------------------------',\n ` Run name : ${dbRunName}`,\n ` Env backup : ${path.basename(backupEnvPath)}`,\n '',\n ' Test databases/schemas created:',\n dbList || ' (none)',\n '',\n ' Next steps:',\n ' 1) Using updated .env with test datasource names',\n ' 2) Run solid seed as usual',\n ' 3) Proceed with the next steps in the workflow',\n '============================================================',\n '',\n ].join('\\n');\n\n console.log(instructions);\n }\n\n async deleteTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (!fs.existsSync(manifestPath)) {\n this.logger.log('No .solidx-test-manifest found; nothing to delete.');\n console.log('No .solidx-test-manifest found; nothing to delete.');\n return;\n }\n\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as {\n runs?: Record<string, { databases?: Record<string, string>; createdAt?: string }>;\n };\n const runs = manifest?.runs ?? {};\n const runNames = Object.keys(runs);\n if (runNames.length === 0) {\n fs.unlinkSync(manifestPath);\n return;\n }\n\n const latestRunName = runNames\n .slice()\n .sort((a, b) => {\n const aCreated = runs[a]?.createdAt ?? '';\n const bCreated = runs[b]?.createdAt ?? '';\n return aCreated.localeCompare(bCreated);\n })\n .pop();\n if (latestRunName) {\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${latestRunName}`);\n if (fs.existsSync(backupEnvPath)) {\n fs.copyFileSync(backupEnvPath, path.join(process.cwd(), '.env'));\n console.log(`Restored .env from ${path.basename(backupEnvPath)}.`);\n fs.unlinkSync(backupEnvPath);\n }\n }\n\n for (const runName of runNames) {\n const envFileName = `.env.${runName}`;\n const envPath = path.join(process.cwd(), envFileName);\n if (fs.existsSync(envPath)) {\n fs.unlinkSync(envPath);\n }\n }\n\n for (const runName of runNames) {\n const databases = runs[runName]?.databases ?? {};\n await this.dropTestDatabaseObjects(databases);\n }\n\n fs.unlinkSync(manifestPath);\n console.log('✔ Test datasource env files and manifest deleted; test databases dropped.');\n }\n\n private get testDataFiles(): any[] {\n const typedSolidCoreMetadata = structuredClone(solidCoreMetadata);\n const testDataFiles = [typedSolidCoreMetadata];\n const enabledModules = getDynamicModuleNamesBasedOnMetadata();\n for (const enabledModule of enabledModules) {\n const enabledModuleSeedFile = `module-metadata/${enabledModule}/${enabledModule}-metadata.json`;\n const fullPath = path.join(process.cwd(), enabledModuleSeedFile);\n\n if (fs.existsSync(fullPath)) {\n const overallMetadata = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));\n testDataFiles.push(overallMetadata);\n }\n }\n\n return testDataFiles;\n }\n\n private async seedTestData(overallMetadata: any): Promise<void> {\n const moduleMetadata: CreateModuleMetadataDto = overallMetadata.moduleMetadata;\n if (!moduleMetadata) {\n throw new Error('Module metadata missing from test data payload.');\n }\n\n // console.log(JSON.stringify(moduleMetadata, null, 2));\n\n const testingRoles: TestingRoleSpec[] = overallMetadata?.testing?.roles ?? [];\n const testingUsers: TestingUserSpec[] = overallMetadata?.testing?.users ?? [];\n const testingData: Array<{ modelUserKey: string; data: Record<string, any> }> = overallMetadata?.testing?.data ?? [];\n\n if (testingRoles.length > 0) {\n await this.seedTestRoles(testingRoles);\n }\n if (testingUsers.length > 0) {\n await this.seedTestUsers(testingUsers);\n }\n\n if (testingData.length === 0) {\n this.logger.debug(`No test data found for ${moduleMetadata.name}`);\n return;\n }\n\n const modelsByName = new Map<string, CreateModelMetadataDto>(\n (moduleMetadata.models ?? []).map((m) => [m.singularName, m]),\n );\n\n for (const entry of testingData) {\n const modelUserKey = entry.modelUserKey;\n const modelDef = modelsByName.get(modelUserKey);\n if (!modelDef) {\n throw new Error(`Test data modelUserKey not found in metadata: ${modelUserKey}`);\n }\n\n const entityRepo = this.resolveRepository(modelUserKey);\n const payload: Record<string, any> = { ...(entry.data ?? {}) };\n\n for (const field of modelDef.fields ?? []) {\n if (field.type === 'relation' && field.relationType === 'many-to-one') {\n const userKeyProp = `${field.name}UserKey`;\n if (!(userKeyProp in payload)) {\n continue;\n }\n\n const userKeyValue = payload[userKeyProp];\n if (userKeyValue === null || userKeyValue === undefined || userKeyValue === '') {\n delete payload[userKeyProp];\n continue;\n }\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = coModelName ? modelsByName.get(coModelName) : null;\n if (!coModelDef) {\n throw new Error(`Test data relation model ${coModelName} not found in metadata, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Test data relation model ${coModelName} is missing userKeyFieldUserKey, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(userKeyValue)\n : await coRepo.findOne({ where: { [coUserKeyField]: userKeyValue } });\n if (!related) {\n throw new Error(`Test data relation not found: ${coModelName}.${coUserKeyField}=${userKeyValue}`);\n }\n\n payload[field.name] = related;\n delete payload[userKeyProp];\n }\n }\n\n // Strip media fields from entity payload — file paths cannot be saved as columns\n const mediaPayload: Record<string, string> = {};\n for (const field of modelDef.fields ?? []) {\n if ((field.type === 'mediaSingle' || field.type === 'mediaMultiple') && payload[field.name] !== undefined) {\n mediaPayload[field.name] = payload[field.name] as string;\n delete payload[field.name];\n }\n }\n\n // Strip many-to-many and one-to-many fields — these are resolved post-save via the relation builder\n const multiRelationPayload: Array<{ field: any; userKeys: string[] }> = [];\n for (const field of modelDef.fields ?? []) {\n if (field.type !== 'relation') continue;\n if (field.relationType !== 'many-to-many' && field.relationType !== 'one-to-many') continue;\n\n const userKeysProp = `${field.name}UserKeys`;\n if (userKeysProp in payload && Array.isArray(payload[userKeysProp])) {\n multiRelationPayload.push({ field, userKeys: payload[userKeysProp] });\n delete payload[userKeysProp];\n }\n // Remove raw field value if accidentally present\n delete payload[field.name];\n }\n\n // Upsert entity, capturing the saved result for post-save steps\n let savedEntity: any;\n const userKeyField = modelDef.userKeyFieldUserKey;\n if (userKeyField && payload[userKeyField] !== undefined) {\n const existing = await entityRepo.findOne({\n where: { [userKeyField]: payload[userKeyField] },\n });\n if (existing) {\n savedEntity = await entityRepo.save(entityRepo.merge(existing, payload));\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n\n if (multiRelationPayload.length > 0) {\n await this.seedMultiRelations(savedEntity.id, modelUserKey, multiRelationPayload, modelsByName);\n }\n\n if (Object.keys(mediaPayload).length > 0) {\n await this.seedEntityMedia(savedEntity.id, modelUserKey, mediaPayload);\n }\n }\n }\n\n private async seedTestRoles(roles: TestingRoleSpec[]): Promise<void> {\n const roleService = this.moduleRef.get(RoleMetadataService, { strict: false });\n if (!roleService) {\n throw new Error('RoleMetadataService not available — cannot seed test roles.');\n }\n\n await roleService.createRolesIfNotExists(roles.map((r) => ({ name: r.name } as any)));\n\n for (const role of roles) {\n const perms = role.permissions ?? [];\n if (perms.length === 0) continue;\n\n if (perms.some((p) => p === '*')) {\n await roleService.addAllPermissionsToRole(role.name);\n this.logger.log(`Bound all permissions to test role \"${role.name}\"`);\n continue;\n }\n\n const expanded = await this.expandPermissionNames(perms);\n if (expanded.length === 0) {\n this.logger.warn(`Test role \"${role.name}\" has permissions declared but none resolved — skipping binding.`);\n continue;\n }\n\n try {\n await roleService.addPermissionsToRole(role.name, expanded);\n } catch (err: any) {\n throw new Error(\n `Failed to bind permissions to test role \"${role.name}\": ${err?.message ?? err}. ` +\n `Did you run \"solid seed\" first so controller permissions are registered?`,\n );\n }\n this.logger.log(`Bound ${expanded.length} permissions to test role \"${role.name}\"`);\n }\n }\n\n private async expandPermissionNames(permissions: string[]): Promise<string[]> {\n const permissionRepo = this.moduleRef.get(PermissionMetadataRepository, { strict: false });\n if (!permissionRepo) {\n throw new Error('PermissionMetadataRepository not available — cannot resolve test role permissions.');\n }\n\n const exact = new Set<string>();\n const prefixes: string[] = [];\n for (const entry of permissions) {\n if (!entry) continue;\n if (entry.endsWith('.*')) {\n prefixes.push(entry.slice(0, -1));\n } else {\n exact.add(entry);\n }\n }\n\n if (prefixes.length > 0) {\n const allPermissions = await permissionRepo.find();\n for (const p of allPermissions) {\n if (prefixes.some((prefix) => p.name.startsWith(prefix))) {\n exact.add(p.name);\n }\n }\n }\n\n return Array.from(exact);\n }\n\n private async seedTestUsers(users: TestingUserSpec[]): Promise<void> {\n const userService = this.moduleRef.get(UserService, { strict: false });\n const authService = this.moduleRef.get(AuthenticationService, { strict: false });\n if (!userService || !authService) {\n throw new Error('UserService / AuthenticationService not available — cannot seed test users.');\n }\n\n for (const user of users) {\n const existing = await userService.findOneByUsername(user.username);\n if (existing) {\n this.logger.debug(`Test user \"${user.username}\" already exists — skipping signUp.`);\n continue;\n }\n\n await authService.signUp({ ...user });\n this.logger.log(`Created test user \"${user.username}\"${user.roles?.length ? ` with roles [${user.roles.join(', ')}]` : ''}`);\n }\n }\n\n private async seedMultiRelations(\n entityId: number,\n modelUserKey: string,\n relations: Array<{ field: any; userKeys: string[] }>,\n modelsByName: Map<string, CreateModelMetadataDto>,\n ): Promise<void> {\n for (const { field, userKeys } of relations) {\n if (!userKeys.length) continue;\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = modelsByName.get(coModelName);\n if (!coModelDef) {\n throw new Error(`Relation model \"${coModelName}\" not found in metadata for field ${modelUserKey}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Relation model \"${coModelName}\" is missing userKeyFieldUserKey, needed to resolve ${modelUserKey}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const resolvedIds: number[] = [];\n for (const uk of userKeys) {\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(uk)\n : await coRepo.findOne({ where: { [coUserKeyField]: uk } });\n if (!related) {\n throw new Error(`Related entity not found: ${coModelName}.${coUserKeyField}=${uk}`);\n }\n resolvedIds.push(related.id);\n }\n\n // Load currently associated entities to diff (set semantics — idempotent)\n const existingRelated: any[] = await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .loadMany();\n const existingIds: number[] = existingRelated.map((e) => e.id);\n\n const toAdd = resolvedIds.filter((id) => !existingIds.includes(id));\n const toRemove = existingIds.filter((id) => !resolvedIds.includes(id));\n\n if (toAdd.length > 0 || toRemove.length > 0) {\n await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .addAndRemove(toAdd, toRemove);\n }\n\n this.logger.debug(`Seeded ${field.relationType} relation ${modelUserKey}.${field.name} entityId=${entityId}: +${toAdd.length} -${toRemove.length}`);\n }\n }\n\n private async seedEntityMedia(\n entityId: number,\n modelUserKey: string,\n mediaPayload: Record<string, string>,\n ): Promise<void> {\n const mediaBasePath = process.env.TEST_UPLOADS_MEDIA_FILE_PATH;\n if (!mediaBasePath) {\n throw new Error('TEST_UPLOADS_MEDIA_FILE_PATH is not set. Cannot seed test media.');\n }\n\n const modelMetadata = await this.modelMetadataService.findOneBySingularName(modelUserKey, {\n fields: {\n model: { userKeyField: true },\n mediaStorageProvider: true,\n },\n });\n\n for (const [fieldName, fileName] of Object.entries(mediaPayload)) {\n if (!fileName) continue;\n\n const fieldMetadata = modelMetadata.fields.find((f) => f.name === fieldName);\n if (!fieldMetadata) {\n throw new Error(`Media field \"${fieldName}\" not found in loaded metadata for model ${modelUserKey}`);\n }\n if (!fieldMetadata.mediaStorageProvider) {\n throw new Error(`Media field \"${fieldName}\" in model ${modelUserKey} has no storage provider configured`);\n }\n\n const storageProviderType = fieldMetadata.mediaStorageProvider.type as MediaStorageProviderType;\n if (storageProviderType !== MediaStorageProviderType.Filesystem) {\n throw new Error(`Test media seeding supports filesystem storage only. Field \"${fieldName}\" uses \"${storageProviderType}\".`);\n }\n\n // Idempotency: skip if media already exists for this entity + field\n const existing = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(\n entityId, fieldMetadata.id, fieldMetadata.model.id,\n );\n if (existing.length > 0) {\n this.logger.debug(`Media already seeded for ${modelUserKey}.${fieldName} entityId=${entityId}, skipping`);\n continue;\n }\n\n const sourcePath = path.join(mediaBasePath, fileName);\n if (!fs.existsSync(sourcePath)) {\n throw new Error(`Test media file not found: ${sourcePath}`);\n }\n\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n const stream = fs.createReadStream(sourcePath);\n await storageProvider.storeStreams([[stream, fileName]], { id: entityId }, fieldMetadata);\n this.logger.debug(`Seeded media for ${modelUserKey}.${fieldName} entityId=${entityId} file=${fileName}`);\n }\n }\n\n private get entityManager(): EntityManager {\n return this.moduleRef.get(EntityManager, { strict: false });\n }\n\n private get modelMetadataService(): ModelMetadataService {\n return this.moduleRef.get(ModelMetadataService, { strict: false });\n }\n\n private get mediaRepository(): MediaRepository {\n return this.moduleRef.get(MediaRepository, { strict: false });\n }\n\n private resolveRepository(modelUserKey: string): any {\n const repoName = `${classify(modelUserKey)}Repository`;\n const providers = this.discoveryService.getProviders();\n const wrapper = providers.find((provider) => provider.name === repoName);\n const repo = wrapper?.instance;\n if (repo) {\n return repo;\n }\n\n try {\n const resolved = this.moduleRef.get(repoName as any, { strict: false });\n if (resolved) {\n return resolved;\n }\n } catch {\n // fall through\n }\n\n throw new Error(`Repository not found for model ${modelUserKey}. Expected provider: ${repoName}`);\n }\n\n private generateDbRunName(): string {\n const adjectives = [\n 'brave', 'bright', 'calm', 'clever', 'curious', 'gentle', 'jolly', 'lively', 'mighty', 'nimble',\n 'proud', 'quick', 'quiet', 'sharp', 'sly', 'steady', 'swift', 'wise', 'witty', 'zesty',\n ];\n const animals = [\n 'lion', 'tiger', 'panther', 'eagle', 'falcon', 'otter', 'wolf', 'fox', 'bear', 'badger',\n 'monkey', 'panda', 'leopard', 'whale', 'dolphin', 'rhino', 'giraffe', 'camel', 'koala', 'lynx',\n ];\n const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];\n const animal = animals[Math.floor(Math.random() * animals.length)];\n return `${adjective}_${animal}`;\n }\n\n private getTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => value.toString().padStart(2, '0');\n return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;\n }\n\n private buildTestEnvContents(baseEnv: string, dbNameByDatasource: Map<string, string>): string {\n const datasourceNameSet = new Set(Array.from(dbNameByDatasource.keys()));\n const lines = baseEnv.split(/\\r?\\n/);\n return lines\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || !trimmed.includes('=')) {\n return line;\n }\n const [rawKey] = line.split('=');\n const key = rawKey.trim();\n if (!key.endsWith('_DATABASE_NAME')) {\n return line;\n }\n const prefix = key.replace(/_DATABASE_NAME$/, '').toLowerCase();\n const matchedDatasource = Array.from(datasourceNameSet).find((name) => name === prefix);\n if (!matchedDatasource) {\n return line;\n }\n const dbName = dbNameByDatasource.get(matchedDatasource);\n if (!dbName) {\n return line;\n }\n return `${key}=${dbName}`;\n })\n .join('\\n');\n }\n\n private async createTestDatabaseObjects(dbNameByDatasource: Map<string, string>): Promise<void> {\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Creating test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`CREATE DATABASE \"${dbName}\"`);\n } else if (type === 'mssql') {\n await queryRunner.query(\n `IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '${dbName}') EXEC('CREATE SCHEMA [${dbName}]')`,\n );\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`CREATE DATABASE IF NOT EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data creation: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private resolveDataSourceByName(datasourceName: string): DataSource {\n const token = datasourceName ? getDataSourceToken(datasourceName) : getDataSourceToken();\n try {\n const ds = this.moduleRef.get<DataSource>(token, { strict: false });\n if (!ds) {\n throw new Error(`No DataSource found for \"${datasourceName}\"`);\n }\n return ds;\n } catch (err: any) {\n throw new Error(`Failed to resolve DataSource \"${datasourceName}\": ${err?.message ?? err}`);\n }\n }\n\n private updateTestManifest(\n dbRunName: string,\n timestamp: string,\n dbNameByDatasource: Map<string, string>,\n ): void {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n let manifest: Record<string, any> = {};\n if (fs.existsSync(manifestPath)) {\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));\n if (parsed && typeof parsed === 'object') {\n manifest = parsed;\n }\n } catch {\n // fall through with empty manifest\n }\n }\n\n if (!manifest.runs || typeof manifest.runs !== 'object') {\n manifest.runs = {};\n }\n\n const databases: Record<string, string> = {};\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n databases[dsName] = dbName;\n }\n\n manifest.runs[dbRunName] = {\n createdAt: timestamp,\n databases,\n };\n\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n private async dropTestDatabaseObjects(databases: Record<string, string>): Promise<void> {\n const entries = Object.entries(databases);\n for (const [dsName, dbName] of entries) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Dropping test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n } else if (type === 'mssql') {\n await this.dropMssqlSchema(queryRunner, dbName);\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data deletion: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private async dropMssqlSchema(queryRunner: ReturnType<DataSource['createQueryRunner']>, schemaName: string): Promise<void> {\n const foreignKeys: Array<{ fk_name: string; table_name: string }> = await queryRunner.query(\n `SELECT fk.name AS fk_name, t.name AS table_name\n FROM sys.foreign_keys fk\n INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE s.name = '${schemaName}'`,\n );\n for (const fk of foreignKeys) {\n await queryRunner.query(`ALTER TABLE [${schemaName}].[${fk.table_name}] DROP CONSTRAINT [${fk.fk_name}]`);\n }\n\n const tables: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const table of tables) {\n await queryRunner.query(`DROP TABLE [${schemaName}].[${table.TABLE_NAME}]`);\n }\n\n const views: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const view of views) {\n await queryRunner.query(`DROP VIEW [${schemaName}].[${view.TABLE_NAME}]`);\n }\n\n await queryRunner.query(`DROP SCHEMA [${schemaName}]`);\n }\n}\n"]}
1
+ {"version":3,"file":"module-test-data.service.js","sourceRoot":"","sources":["../../src/seeders/module-test-data.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { DiscoveryService, ModuleRef } from '@nestjs/core';\nimport { getDataSourceToken } from '@nestjs/typeorm';\nimport { classify } from '../helpers/string.helper';\nimport { DataSource, EntityManager } from 'typeorm';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport solidCoreMetadata from './seed-data/solid-core-metadata.json';\nimport { CreateModuleMetadataDto } from 'src/dtos/create-module-metadata.dto';\nimport { CreateModelMetadataDto } from 'src/dtos/create-model-metadata.dto';\nimport { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';\nimport { getDynamicModuleNamesBasedOnMetadata } from 'src/helpers/module.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { MediaRepository } from 'src/repository/media.repository';\nimport { PermissionMetadataRepository } from 'src/repository/permission-metadata.repository';\nimport { AuthenticationService } from 'src/services/authentication.service';\nimport { ModelMetadataService } from 'src/services/model-metadata.service';\nimport { RoleMetadataService } from 'src/services/role-metadata.service';\nimport { UserService } from 'src/services/user.service';\nimport { getMediaStorageProvider } from 'src/services/mediaStorageProviders';\nimport { TestingRoleSpec, TestingUserSpec } from 'src/testing/contracts/testing-metadata.types';\n\n@Injectable()\nexport class ModuleTestDataService {\n private readonly logger = new Logger(ModuleTestDataService.name);\n\n constructor(\n private readonly moduleRef: ModuleRef,\n private readonly discoveryService: DiscoveryService,\n private readonly solidRegistry: SolidRegistry,\n ) {}\n\n async setupTestData(modulesToTest?: string[]): Promise<void> {\n const testDataFiles = this.testDataFiles;\n const filteredFiles = modulesToTest?.length ? testDataFiles.filter((file) => modulesToTest.includes(file.moduleMetadata?.name)) : testDataFiles;\n\n if (filteredFiles.length === 0) {\n this.logger.warn('No modules matched the provided modulesToTest list.');\n console.log('No modules matched the provided modulesToTest list.');\n return;\n }\n\n for (const overallMetadata of filteredFiles) {\n const moduleName = overallMetadata?.moduleMetadata?.name ?? 'unknown';\n this.logger.log(`Processing test data for module: ${moduleName}`);\n console.log(`Processing test data for module: ${moduleName}`);\n await this.seedTestData(overallMetadata);\n console.log(`✔ Test data setup complete for module: ${moduleName}`);\n }\n }\n\n async createTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (fs.existsSync(manifestPath)) {\n console.log('Existing .solidx-test-manifest found; skipping test datasource creation.');\n return;\n }\n\n const dbRunName = this.generateDbRunName();\n const timestamp = this.getTimestamp();\n const envPath = path.join(process.cwd(), '.env');\n if (!fs.existsSync(envPath)) {\n throw new Error(`Base .env file not found at ${envPath}`);\n }\n\n const datasourceNames = this.solidRegistry\n .getSolidDatabaseModules()\n .map((wrapper) => wrapper.instance?.name?.())\n .filter(Boolean)\n .map((name) => name.toLowerCase()) as string[];\n\n if (datasourceNames.length === 0) {\n throw new Error('No solid database modules registered; cannot create test datasources.');\n }\n\n const dbNameByDatasource = new Map<string, string>();\n for (const dsName of datasourceNames) {\n dbNameByDatasource.set(dsName, `${dsName}_${timestamp}_${dbRunName}`);\n }\n\n const newEnvContents = this.buildTestEnvContents(\n fs.readFileSync(envPath, 'utf-8'),\n dbNameByDatasource,\n );\n\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${dbRunName}`);\n fs.copyFileSync(envPath, backupEnvPath);\n fs.writeFileSync(envPath, newEnvContents);\n console.log(`Backed up .env to ${path.basename(backupEnvPath)} and applied new test datasource names to .env.`);\n\n this.updateTestManifest(dbRunName, timestamp, dbNameByDatasource);\n\n await this.createTestDatabaseObjects(dbNameByDatasource);\n\n const dbList = Array.from(dbNameByDatasource.entries())\n .map(([dsName, dbName]) => `- ${dsName}: ${dbName}`)\n .join('\\n');\n\n const instructions = [\n '',\n '============================================================',\n ' TEST DATASOURCE ENVIRONMENT CREATED',\n '------------------------------------------------------------',\n ` Run name : ${dbRunName}`,\n ` Env backup : ${path.basename(backupEnvPath)}`,\n '',\n ' Test databases/schemas created:',\n dbList || ' (none)',\n '',\n ' Next steps:',\n ' 1) Using updated .env with test datasource names',\n ' 2) Run solid seed as usual',\n ' 3) Proceed with the next steps in the workflow',\n '============================================================',\n '',\n ].join('\\n');\n\n console.log(instructions);\n }\n\n async deleteTestDatasources(): Promise<void> {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n if (!fs.existsSync(manifestPath)) {\n this.logger.log('No .solidx-test-manifest found; nothing to delete.');\n console.log('No .solidx-test-manifest found; nothing to delete.');\n return;\n }\n\n const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as {\n runs?: Record<string, { databases?: Record<string, string>; createdAt?: string }>;\n };\n const runs = manifest?.runs ?? {};\n const runNames = Object.keys(runs);\n if (runNames.length === 0) {\n fs.unlinkSync(manifestPath);\n return;\n }\n\n const latestRunName = runNames\n .slice()\n .sort((a, b) => {\n const aCreated = runs[a]?.createdAt ?? '';\n const bCreated = runs[b]?.createdAt ?? '';\n return aCreated.localeCompare(bCreated);\n })\n .pop();\n if (latestRunName) {\n const backupEnvPath = path.join(process.cwd(), `.env.backup.${latestRunName}`);\n if (fs.existsSync(backupEnvPath)) {\n fs.copyFileSync(backupEnvPath, path.join(process.cwd(), '.env'));\n console.log(`Restored .env from ${path.basename(backupEnvPath)}.`);\n fs.unlinkSync(backupEnvPath);\n }\n }\n\n for (const runName of runNames) {\n const envFileName = `.env.${runName}`;\n const envPath = path.join(process.cwd(), envFileName);\n if (fs.existsSync(envPath)) {\n fs.unlinkSync(envPath);\n }\n }\n\n for (const runName of runNames) {\n const databases = runs[runName]?.databases ?? {};\n await this.dropTestDatabaseObjects(databases);\n }\n\n fs.unlinkSync(manifestPath);\n console.log('✔ Test datasource env files and manifest deleted; test databases dropped.');\n }\n\n private get testDataFiles(): any[] {\n const typedSolidCoreMetadata = structuredClone(solidCoreMetadata);\n const testDataFiles = [typedSolidCoreMetadata];\n const enabledModules = getDynamicModuleNamesBasedOnMetadata();\n for (const enabledModule of enabledModules) {\n const enabledModuleSeedFile = `module-metadata/${enabledModule}/${enabledModule}-metadata.json`;\n const fullPath = path.join(process.cwd(), enabledModuleSeedFile);\n\n if (fs.existsSync(fullPath)) {\n const overallMetadata = JSON.parse(fs.readFileSync(fullPath, 'utf-8'));\n testDataFiles.push(overallMetadata);\n }\n }\n\n return testDataFiles;\n }\n\n private async seedTestData(overallMetadata: any): Promise<void> {\n const moduleMetadata: CreateModuleMetadataDto = overallMetadata.moduleMetadata;\n if (!moduleMetadata) {\n throw new Error('Module metadata missing from test data payload.');\n }\n\n // console.log(JSON.stringify(moduleMetadata, null, 2));\n\n const testingRoles: TestingRoleSpec[] = overallMetadata?.testing?.roles ?? [];\n const testingUsers: TestingUserSpec[] = overallMetadata?.testing?.users ?? [];\n const testingData: Array<{ modelUserKey: string; data: Record<string, any> }> = overallMetadata?.testing?.data ?? [];\n\n if (testingRoles.length > 0) {\n await this.seedTestRoles(testingRoles);\n }\n if (testingUsers.length > 0) {\n await this.seedTestUsers(testingUsers);\n }\n\n if (testingData.length === 0) {\n this.logger.debug(`No test data found for ${moduleMetadata.name}`);\n return;\n }\n\n const modelsByName = new Map<string, CreateModelMetadataDto>(\n (moduleMetadata.models ?? []).map((m) => [m.singularName, m]),\n );\n\n for (const entry of testingData) {\n const modelUserKey = entry.modelUserKey;\n const modelDef = modelsByName.get(modelUserKey);\n if (!modelDef) {\n throw new Error(`Test data modelUserKey not found in metadata: ${modelUserKey}`);\n }\n\n const entityRepo = this.resolveRepository(modelUserKey);\n const payload: Record<string, any> = { ...(entry.data ?? {}) };\n\n for (const field of modelDef.fields ?? []) {\n if (field.type === 'relation' && field.relationType === 'many-to-one') {\n const userKeyProp = `${field.name}UserKey`;\n if (!(userKeyProp in payload)) {\n continue;\n }\n\n const userKeyValue = payload[userKeyProp];\n if (userKeyValue === null || userKeyValue === undefined || userKeyValue === '') {\n delete payload[userKeyProp];\n continue;\n }\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = coModelName ? modelsByName.get(coModelName) : null;\n if (!coModelDef) {\n throw new Error(`Test data relation model ${coModelName} not found in metadata, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Test data relation model ${coModelName} is missing userKeyFieldUserKey, when attempting to resolve field ${modelDef.singularName}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(userKeyValue)\n : await coRepo.findOne({ where: { [coUserKeyField]: userKeyValue } });\n if (!related) {\n throw new Error(`Test data relation not found: ${coModelName}.${coUserKeyField}=${userKeyValue}`);\n }\n\n payload[field.name] = related;\n delete payload[userKeyProp];\n }\n }\n\n // Strip media fields from entity payload — file paths cannot be saved as columns\n const mediaPayload: Record<string, string> = {};\n for (const field of modelDef.fields ?? []) {\n if ((field.type === 'mediaSingle' || field.type === 'mediaMultiple') && payload[field.name] !== undefined) {\n mediaPayload[field.name] = payload[field.name] as string;\n delete payload[field.name];\n }\n }\n\n // Strip many-to-many and one-to-many fields — these are resolved post-save via the relation builder\n const multiRelationPayload: Array<{ field: any; userKeys: string[] }> = [];\n for (const field of modelDef.fields ?? []) {\n if (field.type !== 'relation') continue;\n if (field.relationType !== 'many-to-many' && field.relationType !== 'one-to-many') continue;\n\n const userKeysProp = `${field.name}UserKeys`;\n if (userKeysProp in payload && Array.isArray(payload[userKeysProp])) {\n multiRelationPayload.push({ field, userKeys: payload[userKeysProp] });\n delete payload[userKeysProp];\n }\n // Remove raw field value if accidentally present\n delete payload[field.name];\n }\n\n // Upsert entity, capturing the saved result for post-save steps\n let savedEntity: any;\n const userKeyField = modelDef.userKeyFieldUserKey;\n if (userKeyField && payload[userKeyField] !== undefined) {\n const existing = await entityRepo.findOne({\n where: { [userKeyField]: payload[userKeyField] },\n });\n if (existing) {\n savedEntity = await entityRepo.save(entityRepo.merge(existing, payload));\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n } else {\n savedEntity = await entityRepo.save(entityRepo.create(payload));\n }\n\n if (multiRelationPayload.length > 0) {\n await this.seedMultiRelations(savedEntity.id, modelUserKey, multiRelationPayload, modelsByName);\n }\n\n if (Object.keys(mediaPayload).length > 0) {\n await this.seedEntityMedia(savedEntity.id, modelUserKey, mediaPayload);\n }\n }\n }\n\n private async seedTestRoles(roles: TestingRoleSpec[]): Promise<void> {\n const roleService = this.moduleRef.get(RoleMetadataService, { strict: false });\n if (!roleService) {\n throw new Error('RoleMetadataService not available — cannot seed test roles.');\n }\n\n await roleService.createRolesIfNotExists(roles.map((r) => ({ name: r.name } as any)));\n\n for (const role of roles) {\n const perms = role.permissions ?? [];\n if (perms.length === 0) continue;\n\n if (perms.some((p) => p === '*')) {\n await roleService.addAllPermissionsToRole(role.name);\n this.logger.log(`Bound all permissions to test role \"${role.name}\"`);\n continue;\n }\n\n const expanded = await this.expandPermissionNames(perms);\n if (expanded.length === 0) {\n this.logger.warn(`Test role \"${role.name}\" has permissions declared but none resolved — skipping binding.`);\n continue;\n }\n\n try {\n await roleService.addPermissionsToRole(role.name, expanded);\n } catch (err: any) {\n throw new Error(\n `Failed to bind permissions to test role \"${role.name}\": ${err?.message ?? err}. ` +\n `Did you run \"solid seed\" first so controller permissions are registered?`,\n );\n }\n this.logger.log(`Bound ${expanded.length} permissions to test role \"${role.name}\"`);\n }\n }\n\n private async expandPermissionNames(permissions: string[]): Promise<string[]> {\n const permissionRepo = this.moduleRef.get(PermissionMetadataRepository, { strict: false });\n if (!permissionRepo) {\n throw new Error('PermissionMetadataRepository not available — cannot resolve test role permissions.');\n }\n\n const exact = new Set<string>();\n const prefixes: string[] = [];\n for (const entry of permissions) {\n if (!entry) continue;\n if (entry.endsWith('.*')) {\n prefixes.push(entry.slice(0, -1));\n } else {\n exact.add(entry);\n }\n }\n\n if (prefixes.length > 0) {\n const allPermissions = await permissionRepo.find();\n for (const p of allPermissions) {\n if (prefixes.some((prefix) => p.name.startsWith(prefix))) {\n exact.add(p.name);\n }\n }\n }\n\n return Array.from(exact);\n }\n\n private async seedTestUsers(users: TestingUserSpec[]): Promise<void> {\n const userService = this.moduleRef.get(UserService, { strict: false });\n const authService = this.moduleRef.get(AuthenticationService, { strict: false });\n if (!userService || !authService) {\n throw new Error('UserService / AuthenticationService not available — cannot seed test users.');\n }\n\n for (const user of users) {\n const existing = await userService.findOneByUsername(user.username);\n if (existing) {\n this.logger.debug(`Test user \"${user.username}\" already exists — skipping signUp.`);\n continue;\n }\n\n await authService.signUp({ ...user });\n this.logger.log(`Created test user \"${user.username}\"${user.roles?.length ? ` with roles [${user.roles.join(', ')}]` : ''}`);\n }\n }\n\n private async seedMultiRelations(\n entityId: number,\n modelUserKey: string,\n relations: Array<{ field: any; userKeys: string[] }>,\n modelsByName: Map<string, CreateModelMetadataDto>,\n ): Promise<void> {\n for (const { field, userKeys } of relations) {\n if (!userKeys.length) continue;\n\n const coModelName = field.relationCoModelSingularName;\n const coModelDef = modelsByName.get(coModelName);\n if (!coModelDef) {\n throw new Error(`Relation model \"${coModelName}\" not found in metadata for field ${modelUserKey}.${field.name}`);\n }\n const coUserKeyField = coModelDef.userKeyFieldUserKey;\n if (!coUserKeyField) {\n throw new Error(`Relation model \"${coModelName}\" is missing userKeyFieldUserKey, needed to resolve ${modelUserKey}.${field.name}`);\n }\n\n const coRepo = this.resolveRepository(coModelName);\n const resolvedIds: number[] = [];\n for (const uk of userKeys) {\n const related = typeof coRepo.findOneByUserKey === 'function'\n ? await coRepo.findOneByUserKey(uk)\n : await coRepo.findOne({ where: { [coUserKeyField]: uk } });\n if (!related) {\n throw new Error(`Related entity not found: ${coModelName}.${coUserKeyField}=${uk}`);\n }\n resolvedIds.push(related.id);\n }\n\n // Load currently associated entities to diff (set semantics — idempotent)\n const existingRelated: any[] = await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .loadMany();\n const existingIds: number[] = existingRelated.map((e) => e.id);\n\n const toAdd = resolvedIds.filter((id) => !existingIds.includes(id));\n const toRemove = existingIds.filter((id) => !resolvedIds.includes(id));\n\n if (toAdd.length > 0 || toRemove.length > 0) {\n await this.entityManager\n .createQueryBuilder()\n .relation(classify(modelUserKey), field.name)\n .of(entityId)\n .addAndRemove(toAdd, toRemove);\n }\n\n this.logger.debug(`Seeded ${field.relationType} relation ${modelUserKey}.${field.name} entityId=${entityId}: +${toAdd.length} -${toRemove.length}`);\n }\n }\n\n private async seedEntityMedia(\n entityId: number,\n modelUserKey: string,\n mediaPayload: Record<string, string>,\n ): Promise<void> {\n const mediaBasePath = process.env.TEST_UPLOADS_MEDIA_FILE_PATH;\n if (!mediaBasePath) {\n throw new Error('TEST_UPLOADS_MEDIA_FILE_PATH is not set. Cannot seed test media.');\n }\n\n const modelMetadata = await this.modelMetadataService.findOneBySingularName(modelUserKey, {\n fields: {\n model: { userKeyField: true },\n mediaStorageProvider: true,\n },\n });\n\n for (const [fieldName, fileName] of Object.entries(mediaPayload)) {\n if (!fileName) continue;\n\n const fieldMetadata = modelMetadata.fields.find((f) => f.name === fieldName);\n if (!fieldMetadata) {\n throw new Error(`Media field \"${fieldName}\" not found in loaded metadata for model ${modelUserKey}`);\n }\n if (!fieldMetadata.mediaStorageProvider) {\n throw new Error(`Media field \"${fieldName}\" in model ${modelUserKey} has no storage provider configured`);\n }\n\n const storageProviderType = fieldMetadata.mediaStorageProvider.type as MediaStorageProviderType;\n if (storageProviderType !== MediaStorageProviderType.Filesystem) {\n throw new Error(`Test media seeding supports filesystem storage only. Field \"${fieldName}\" uses \"${storageProviderType}\".`);\n }\n\n // Idempotency: skip if media already exists for this entity + field\n const existing = await this.mediaRepository.findByEntityIdAndFieldIdAndModelMetadataId(\n entityId, fieldMetadata.id, fieldMetadata.model.id,\n );\n if (existing.length > 0) {\n this.logger.debug(`Media already seeded for ${modelUserKey}.${fieldName} entityId=${entityId}, skipping`);\n continue;\n }\n\n const sourcePath = path.join(mediaBasePath, fileName);\n if (!fs.existsSync(sourcePath)) {\n throw new Error(`Test media file not found: ${sourcePath}`);\n }\n\n const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);\n const stream = fs.createReadStream(sourcePath);\n await storageProvider.storeStreams([[stream, fileName]], { id: entityId }, fieldMetadata);\n this.logger.debug(`Seeded media for ${modelUserKey}.${fieldName} entityId=${entityId} file=${fileName}`);\n }\n }\n\n private get entityManager(): EntityManager {\n return this.moduleRef.get(EntityManager, { strict: false });\n }\n\n private get modelMetadataService(): ModelMetadataService {\n return this.moduleRef.get(ModelMetadataService, { strict: false });\n }\n\n private get mediaRepository(): MediaRepository {\n return this.moduleRef.get(MediaRepository, { strict: false });\n }\n\n private resolveRepository(modelUserKey: string): any {\n const repoName = `${classify(modelUserKey)}Repository`;\n const providers = this.discoveryService.getProviders();\n const wrapper = providers.find((provider) => provider.name === repoName);\n const repo = wrapper?.instance;\n if (repo) {\n return repo;\n }\n\n try {\n const resolved = this.moduleRef.get(repoName as any, { strict: false });\n if (resolved) {\n return resolved;\n }\n } catch {\n // fall through\n }\n\n throw new Error(`Repository not found for model ${modelUserKey}. Expected provider: ${repoName}`);\n }\n\n private generateDbRunName(): string {\n const adjectives = [\n 'brave', 'bright', 'calm', 'clever', 'curious', 'gentle', 'jolly', 'lively', 'mighty', 'nimble',\n 'proud', 'quick', 'quiet', 'sharp', 'sly', 'steady', 'swift', 'wise', 'witty', 'zesty',\n ];\n const animals = [\n 'lion', 'tiger', 'panther', 'eagle', 'falcon', 'otter', 'wolf', 'fox', 'bear', 'badger',\n 'monkey', 'panda', 'leopard', 'whale', 'dolphin', 'rhino', 'giraffe', 'camel', 'koala', 'lynx',\n ];\n const adjective = adjectives[Math.floor(Math.random() * adjectives.length)];\n const animal = animals[Math.floor(Math.random() * animals.length)];\n return `${adjective}_${animal}`;\n }\n\n private getTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => value.toString().padStart(2, '0');\n return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;\n }\n\n private buildTestEnvContents(baseEnv: string, dbNameByDatasource: Map<string, string>): string {\n const datasourceNameSet = new Set(Array.from(dbNameByDatasource.keys()));\n const lines = baseEnv.split(/\\r?\\n/);\n return lines\n .map((line) => {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || !trimmed.includes('=')) {\n return line;\n }\n const [rawKey] = line.split('=');\n const key = rawKey.trim();\n if (!key.endsWith('_DATABASE_NAME')) {\n return line;\n }\n const prefix = key.replace(/_DATABASE_NAME$/, '').toLowerCase();\n const matchedDatasource = Array.from(datasourceNameSet).find((name) => name === prefix);\n if (!matchedDatasource) {\n return line;\n }\n const dbName = dbNameByDatasource.get(matchedDatasource);\n if (!dbName) {\n return line;\n }\n return `${key}=${dbName}`;\n })\n .join('\\n');\n }\n\n private async createTestDatabaseObjects(dbNameByDatasource: Map<string, string>): Promise<void> {\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Creating test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`CREATE DATABASE \"${dbName}\"`);\n } else if (type === 'mssql') {\n await queryRunner.query(\n `IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = '${dbName}') EXEC('CREATE SCHEMA [${dbName}]')`,\n );\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`CREATE DATABASE IF NOT EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data creation: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private resolveDataSourceByName(datasourceName: string): DataSource {\n const token = datasourceName ? getDataSourceToken(datasourceName) : getDataSourceToken();\n try {\n const ds = this.moduleRef.get<DataSource>(token, { strict: false });\n if (!ds) {\n throw new Error(`No DataSource found for \"${datasourceName}\"`);\n }\n return ds;\n } catch (err: any) {\n throw new Error(`Failed to resolve DataSource \"${datasourceName}\": ${err?.message ?? err}`);\n }\n }\n\n private updateTestManifest(\n dbRunName: string,\n timestamp: string,\n dbNameByDatasource: Map<string, string>,\n ): void {\n const manifestPath = path.join(process.cwd(), '.solidx-test-manifest');\n let manifest: Record<string, any> = {};\n if (fs.existsSync(manifestPath)) {\n try {\n const parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));\n if (parsed && typeof parsed === 'object') {\n manifest = parsed;\n }\n } catch {\n // fall through with empty manifest\n }\n }\n\n if (!manifest.runs || typeof manifest.runs !== 'object') {\n manifest.runs = {};\n }\n\n const databases: Record<string, string> = {};\n for (const [dsName, dbName] of dbNameByDatasource.entries()) {\n databases[dsName] = dbName;\n }\n\n manifest.runs[dbRunName] = {\n createdAt: timestamp,\n databases,\n };\n\n fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));\n }\n\n private async dropTestDatabaseObjects(databases: Record<string, string>): Promise<void> {\n const entries = Object.entries(databases);\n for (const [dsName, dbName] of entries) {\n const dataSource = this.resolveDataSourceByName(dsName);\n if (!dataSource.isInitialized) {\n await dataSource.initialize();\n }\n\n console.log(`Dropping test database/schema \"${dbName}\" on datasource \"${dsName}\"...`);\n\n const queryRunner = dataSource.createQueryRunner();\n try {\n const type = dataSource.options.type;\n if (type === 'postgres') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \"${dbName}\"`);\n } else if (type === 'mssql') {\n await this.dropMssqlSchema(queryRunner, dbName);\n } else if (type === 'mysql' || type === 'mariadb') {\n await queryRunner.query(`DROP DATABASE IF EXISTS \\`${dbName}\\``);\n } else {\n throw new Error(`Unsupported database type for test data deletion: ${type}`);\n }\n } finally {\n await queryRunner.release();\n }\n }\n }\n\n private async dropMssqlSchema(queryRunner: ReturnType<DataSource['createQueryRunner']>, schemaName: string): Promise<void> {\n const foreignKeys: Array<{ fk_name: string; table_name: string }> = await queryRunner.query(\n `SELECT fk.name AS fk_name, t.name AS table_name\n FROM sys.foreign_keys fk\n INNER JOIN sys.tables t ON fk.parent_object_id = t.object_id\n INNER JOIN sys.schemas s ON t.schema_id = s.schema_id\n WHERE s.name = '${schemaName}'`,\n );\n for (const fk of foreignKeys) {\n await queryRunner.query(`ALTER TABLE [${schemaName}].[${fk.table_name}] DROP CONSTRAINT [${fk.fk_name}]`);\n }\n\n const tables: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const table of tables) {\n await queryRunner.query(`DROP TABLE [${schemaName}].[${table.TABLE_NAME}]`);\n }\n\n const views: Array<{ TABLE_NAME: string }> = await queryRunner.query(\n `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '${schemaName}'`,\n );\n for (const view of views) {\n await queryRunner.query(`DROP VIEW [${schemaName}].[${view.TABLE_NAME}]`);\n }\n\n await queryRunner.query(`DROP SCHEMA [${schemaName}]`);\n }\n}\n"]}