@lenne.tech/nest-server 12.0.0 → 12.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (693) hide show
  1. package/.claude/rules/architecture.md +6 -1
  2. package/.claude/rules/better-auth.md +46 -0
  3. package/.claude/rules/configurable-features.md +3 -2
  4. package/.claude/rules/package-management.md +24 -2
  5. package/.claude/rules/persistence.md +100 -0
  6. package/.claude/rules/role-system.md +9 -0
  7. package/.claude/rules/testing.md +116 -18
  8. package/CLAUDE.md +21 -2
  9. package/FRAMEWORK-API.md +6 -4
  10. package/README.md +106 -34
  11. package/dist/core/common/decorators/unified-field.decorator.d.ts +2 -1
  12. package/dist/core/common/decorators/unified-field.decorator.js +4 -1
  13. package/dist/core/common/decorators/unified-field.decorator.js.map +1 -1
  14. package/dist/core/common/filters/mongoose-cast-error.filter.d.ts +7 -5
  15. package/dist/core/common/filters/mongoose-cast-error.filter.js +3 -2
  16. package/dist/core/common/filters/mongoose-cast-error.filter.js.map +1 -1
  17. package/dist/core/common/helpers/db.helper.d.ts +2 -1
  18. package/dist/core/common/helpers/db.helper.js +32 -26
  19. package/dist/core/common/helpers/db.helper.js.map +1 -1
  20. package/dist/core/common/helpers/decorator.helper.d.ts +1 -1
  21. package/dist/core/common/helpers/filter.helper.d.ts +2 -1
  22. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  23. package/dist/core/common/helpers/gridfs.helper.d.ts +4 -4
  24. package/dist/core/common/helpers/gridfs.helper.js +14 -6
  25. package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
  26. package/dist/core/common/helpers/id.helper.d.ts +4 -1
  27. package/dist/core/common/helpers/id.helper.js +10 -4
  28. package/dist/core/common/helpers/id.helper.js.map +1 -1
  29. package/dist/core/common/helpers/model.helper.js +5 -5
  30. package/dist/core/common/helpers/model.helper.js.map +1 -1
  31. package/dist/core/common/helpers/service.helper.js +3 -3
  32. package/dist/core/common/helpers/service.helper.js.map +1 -1
  33. package/dist/core/common/interfaces/server-options.interface.d.ts +18 -2
  34. package/dist/core/common/interfaces/service-options.interface.d.ts +2 -2
  35. package/dist/core/common/models/core-persistence.model.d.ts +1 -2
  36. package/dist/core/common/models/core-persistence.model.js +3 -3
  37. package/dist/core/common/models/core-persistence.model.js.map +1 -1
  38. package/dist/core/common/persistence/core-persistence.lifecycle.d.ts +9 -0
  39. package/dist/core/common/persistence/core-persistence.lifecycle.js +38 -0
  40. package/dist/core/common/persistence/core-persistence.lifecycle.js.map +1 -0
  41. package/dist/core/common/persistence/core-persistence.module.d.ts +9 -0
  42. package/dist/core/common/persistence/core-persistence.module.js +76 -0
  43. package/dist/core/common/persistence/core-persistence.module.js.map +1 -0
  44. package/dist/core/common/persistence/data-source.config.d.ts +33 -0
  45. package/dist/core/common/persistence/data-source.config.js +151 -0
  46. package/dist/core/common/persistence/data-source.config.js.map +1 -0
  47. package/dist/core/common/persistence/data-source.runtime.d.ts +45 -0
  48. package/dist/core/common/persistence/data-source.runtime.js +278 -0
  49. package/dist/core/common/persistence/data-source.runtime.js.map +1 -0
  50. package/dist/core/common/persistence/data-store.interface.d.ts +73 -0
  51. package/dist/core/common/persistence/data-store.interface.js +2 -0
  52. package/dist/core/common/persistence/data-store.interface.js.map +1 -0
  53. package/dist/core/common/persistence/expiry-sweep.d.ts +12 -0
  54. package/dist/core/common/persistence/expiry-sweep.js +55 -0
  55. package/dist/core/common/persistence/expiry-sweep.js.map +1 -0
  56. package/dist/core/common/persistence/id-format.d.ts +3 -0
  57. package/dist/core/common/persistence/id-format.js +21 -0
  58. package/dist/core/common/persistence/id-format.js.map +1 -0
  59. package/dist/core/common/persistence/infrastructure-locks.d.ts +13 -0
  60. package/dist/core/common/persistence/infrastructure-locks.js +35 -0
  61. package/dist/core/common/persistence/infrastructure-locks.js.map +1 -0
  62. package/dist/core/common/persistence/inject-store.decorator.d.ts +1 -0
  63. package/dist/core/common/persistence/inject-store.decorator.js +6 -0
  64. package/dist/core/common/persistence/inject-store.decorator.js.map +1 -0
  65. package/dist/core/common/persistence/lock-store.interface.d.ts +5 -0
  66. package/dist/core/common/persistence/lock-store.interface.js +2 -0
  67. package/dist/core/common/persistence/lock-store.interface.js.map +1 -0
  68. package/dist/core/common/persistence/model-descriptor.interface.d.ts +36 -0
  69. package/dist/core/common/persistence/model-descriptor.interface.js +2 -0
  70. package/dist/core/common/persistence/model-descriptor.interface.js.map +1 -0
  71. package/dist/core/common/persistence/model-metadata.registry.d.ts +14 -0
  72. package/dist/core/common/persistence/model-metadata.registry.js +194 -0
  73. package/dist/core/common/persistence/model-metadata.registry.js.map +1 -0
  74. package/dist/core/common/persistence/mongo/collection-name.d.ts +2 -0
  75. package/dist/core/common/persistence/mongo/collection-name.js +73 -0
  76. package/dist/core/common/persistence/mongo/collection-name.js.map +1 -0
  77. package/dist/core/common/persistence/mongo/declared-schema.view.d.ts +11 -0
  78. package/dist/core/common/persistence/mongo/declared-schema.view.js +292 -0
  79. package/dist/core/common/persistence/mongo/declared-schema.view.js.map +1 -0
  80. package/dist/core/common/persistence/mongo/hex-object-id.d.ts +13 -0
  81. package/dist/core/common/persistence/mongo/hex-object-id.js +54 -0
  82. package/dist/core/common/persistence/mongo/hex-object-id.js.map +1 -0
  83. package/dist/core/common/persistence/mongo/model-declarations.d.ts +35 -0
  84. package/dist/core/common/persistence/mongo/model-declarations.js +80 -0
  85. package/dist/core/common/persistence/mongo/model-declarations.js.map +1 -0
  86. package/dist/core/common/persistence/mongo/mongo-packages.d.ts +15 -0
  87. package/dist/core/common/persistence/mongo/mongo-packages.js +66 -0
  88. package/dist/core/common/persistence/mongo/mongo-packages.js.map +1 -0
  89. package/dist/core/common/persistence/mongo/mongoose-compat.d.ts +22 -0
  90. package/dist/core/common/persistence/mongo/mongoose-compat.js +65 -0
  91. package/dist/core/common/persistence/mongo/mongoose-compat.js.map +1 -0
  92. package/dist/core/common/persistence/mongo/no-mongo-connection.module.d.ts +2 -0
  93. package/dist/core/common/persistence/mongo/no-mongo-connection.module.js +19 -0
  94. package/dist/core/common/persistence/mongo/no-mongo-connection.module.js.map +1 -0
  95. package/dist/core/common/persistence/mongo-lock-store.d.ts +21 -0
  96. package/dist/core/common/persistence/mongo-lock-store.js +72 -0
  97. package/dist/core/common/persistence/mongo-lock-store.js.map +1 -0
  98. package/dist/core/common/persistence/mongoose-data-store.d.ts +33 -0
  99. package/dist/core/common/persistence/mongoose-data-store.js +187 -0
  100. package/dist/core/common/persistence/mongoose-data-store.js.map +1 -0
  101. package/dist/core/common/persistence/neutral-populate.d.ts +6 -0
  102. package/dist/core/common/persistence/neutral-populate.js +72 -0
  103. package/dist/core/common/persistence/neutral-populate.js.map +1 -0
  104. package/dist/core/common/persistence/persisted-model.decorator.d.ts +6 -0
  105. package/dist/core/common/persistence/persisted-model.decorator.js +24 -0
  106. package/dist/core/common/persistence/persisted-model.decorator.js.map +1 -0
  107. package/dist/core/common/persistence/persistence-runtime.registry.d.ts +61 -0
  108. package/dist/core/common/persistence/persistence-runtime.registry.js +47 -0
  109. package/dist/core/common/persistence/persistence-runtime.registry.js.map +1 -0
  110. package/dist/core/common/persistence/persistence.tokens.d.ts +1 -0
  111. package/dist/core/common/persistence/persistence.tokens.js +4 -0
  112. package/dist/core/common/persistence/persistence.tokens.js.map +1 -0
  113. package/dist/core/common/persistence/policies/audit.policy.d.ts +8 -0
  114. package/dist/core/common/persistence/policies/audit.policy.js +37 -0
  115. package/dist/core/common/persistence/policies/audit.policy.js.map +1 -0
  116. package/dist/core/common/persistence/policies/password.policy.d.ts +3 -0
  117. package/dist/core/common/persistence/policies/password.policy.js +46 -0
  118. package/dist/core/common/persistence/policies/password.policy.js.map +1 -0
  119. package/dist/core/common/persistence/policies/role-guard.policy.d.ts +3 -0
  120. package/dist/core/common/persistence/policies/role-guard.policy.js +46 -0
  121. package/dist/core/common/persistence/policies/role-guard.policy.js.map +1 -0
  122. package/dist/core/common/persistence/policies/system-role.policy.d.ts +5 -0
  123. package/dist/core/common/persistence/policies/system-role.policy.js +46 -0
  124. package/dist/core/common/persistence/policies/system-role.policy.js.map +1 -0
  125. package/dist/core/common/persistence/policies/tenant.policy.d.ts +19 -0
  126. package/dist/core/common/persistence/policies/tenant.policy.js +120 -0
  127. package/dist/core/common/persistence/policies/tenant.policy.js.map +1 -0
  128. package/dist/core/common/persistence/routed-model.guard.d.ts +4 -0
  129. package/dist/core/common/persistence/routed-model.guard.js +73 -0
  130. package/dist/core/common/persistence/routed-model.guard.js.map +1 -0
  131. package/dist/core/common/persistence/sql/mysql/mysql-data-store.d.ts +46 -0
  132. package/dist/core/common/persistence/sql/mysql/mysql-data-store.js +350 -0
  133. package/dist/core/common/persistence/sql/mysql/mysql-data-store.js.map +1 -0
  134. package/dist/core/common/persistence/sql/mysql/mysql-executor.d.ts +13 -0
  135. package/dist/core/common/persistence/sql/mysql/mysql-executor.js +194 -0
  136. package/dist/core/common/persistence/sql/mysql/mysql-executor.js.map +1 -0
  137. package/dist/core/common/persistence/sql/mysql/mysql-lock-store.d.ts +11 -0
  138. package/dist/core/common/persistence/sql/mysql/mysql-lock-store.js +55 -0
  139. package/dist/core/common/persistence/sql/mysql/mysql-lock-store.js.map +1 -0
  140. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.d.ts +36 -0
  141. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js +288 -0
  142. package/dist/core/common/persistence/sql/mysql/mysql-schema.compiler.js.map +1 -0
  143. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.d.ts +19 -0
  144. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js +328 -0
  145. package/dist/core/common/persistence/sql/mysql/mysql-schema.migrator.js.map +1 -0
  146. package/dist/core/common/persistence/sql/mysql/mysql-session.d.ts +13 -0
  147. package/dist/core/common/persistence/sql/mysql/mysql-session.js +85 -0
  148. package/dist/core/common/persistence/sql/mysql/mysql-session.js.map +1 -0
  149. package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.d.ts +9 -0
  150. package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.js +264 -0
  151. package/dist/core/common/persistence/sql/mysql/mysql-update.compiler.js.map +1 -0
  152. package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.d.ts +20 -0
  153. package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.js +519 -0
  154. package/dist/core/common/persistence/sql/mysql/mysql-where.compiler.js.map +1 -0
  155. package/dist/core/common/persistence/sql/postgres/postgres-lock-store.d.ts +11 -0
  156. package/dist/core/common/persistence/sql/postgres/postgres-lock-store.js +44 -0
  157. package/dist/core/common/persistence/sql/postgres/postgres-lock-store.js.map +1 -0
  158. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.d.ts +42 -0
  159. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js +220 -0
  160. package/dist/core/common/persistence/sql/postgres/postgres-schema.compiler.js.map +1 -0
  161. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.d.ts +12 -0
  162. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js +315 -0
  163. package/dist/core/common/persistence/sql/postgres/postgres-schema.migrator.js.map +1 -0
  164. package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.d.ts +5 -0
  165. package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.js +225 -0
  166. package/dist/core/common/persistence/sql/postgres/postgres-update.compiler.js.map +1 -0
  167. package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.d.ts +13 -0
  168. package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.js +484 -0
  169. package/dist/core/common/persistence/sql/postgres/postgres-where.compiler.js.map +1 -0
  170. package/dist/core/common/persistence/sql/sql-cast.d.ts +2 -0
  171. package/dist/core/common/persistence/sql/sql-cast.js +194 -0
  172. package/dist/core/common/persistence/sql/sql-cast.js.map +1 -0
  173. package/dist/core/common/persistence/sql/sql-data-store.d.ts +79 -0
  174. package/dist/core/common/persistence/sql/sql-data-store.js +592 -0
  175. package/dist/core/common/persistence/sql/sql-data-store.js.map +1 -0
  176. package/dist/core/common/persistence/sql/sql-dialect.d.ts +20 -0
  177. package/dist/core/common/persistence/sql/sql-dialect.js +38 -0
  178. package/dist/core/common/persistence/sql/sql-dialect.js.map +1 -0
  179. package/dist/core/common/persistence/sql/sql-errors.d.ts +17 -0
  180. package/dist/core/common/persistence/sql/sql-errors.js +25 -0
  181. package/dist/core/common/persistence/sql/sql-errors.js.map +1 -0
  182. package/dist/core/common/persistence/sql/sql-executor.factory.d.ts +11 -0
  183. package/dist/core/common/persistence/sql/sql-executor.factory.js +199 -0
  184. package/dist/core/common/persistence/sql/sql-executor.factory.js.map +1 -0
  185. package/dist/core/common/persistence/sql/sql-executor.interface.d.ts +32 -0
  186. package/dist/core/common/persistence/sql/sql-executor.interface.js +2 -0
  187. package/dist/core/common/persistence/sql/sql-executor.interface.js.map +1 -0
  188. package/dist/core/common/persistence/sql/sql-naming.d.ts +15 -0
  189. package/dist/core/common/persistence/sql/sql-naming.js +90 -0
  190. package/dist/core/common/persistence/sql/sql-naming.js.map +1 -0
  191. package/dist/core/common/persistence/sql/sql-schema.shared.d.ts +25 -0
  192. package/dist/core/common/persistence/sql/sql-schema.shared.js +69 -0
  193. package/dist/core/common/persistence/sql/sql-schema.shared.js.map +1 -0
  194. package/dist/core/common/persistence/sql/sql-session.d.ts +6 -0
  195. package/dist/core/common/persistence/sql/sql-session.js +78 -0
  196. package/dist/core/common/persistence/sql/sql-session.js.map +1 -0
  197. package/dist/core/common/persistence/sql/where-shared.d.ts +18 -0
  198. package/dist/core/common/persistence/sql/where-shared.js +93 -0
  199. package/dist/core/common/persistence/sql/where-shared.js.map +1 -0
  200. package/dist/core/common/persistence/store-guards.d.ts +10 -0
  201. package/dist/core/common/persistence/store-guards.js +49 -0
  202. package/dist/core/common/persistence/store-guards.js.map +1 -0
  203. package/dist/core/common/persistence/store-upsert.d.ts +2 -0
  204. package/dist/core/common/persistence/store-upsert.js +20 -0
  205. package/dist/core/common/persistence/store-upsert.js.map +1 -0
  206. package/dist/core/common/persistence/unavailable-store.d.ts +2 -0
  207. package/dist/core/common/persistence/unavailable-store.js +53 -0
  208. package/dist/core/common/persistence/unavailable-store.js.map +1 -0
  209. package/dist/core/common/persistence/unsupported-capability.error.d.ts +3 -0
  210. package/dist/core/common/persistence/unsupported-capability.error.js +4 -0
  211. package/dist/core/common/persistence/unsupported-capability.error.js.map +1 -0
  212. package/dist/core/common/plugins/mongoose-audit-fields.plugin.js +24 -68
  213. package/dist/core/common/plugins/mongoose-audit-fields.plugin.js.map +1 -1
  214. package/dist/core/common/plugins/mongoose-id.plugin.js +3 -0
  215. package/dist/core/common/plugins/mongoose-id.plugin.js.map +1 -1
  216. package/dist/core/common/plugins/mongoose-password.plugin.d.ts +1 -3
  217. package/dist/core/common/plugins/mongoose-password.plugin.js +2 -45
  218. package/dist/core/common/plugins/mongoose-password.plugin.js.map +1 -1
  219. package/dist/core/common/plugins/mongoose-role-guard.plugin.js +5 -46
  220. package/dist/core/common/plugins/mongoose-role-guard.plugin.js.map +1 -1
  221. package/dist/core/common/plugins/mongoose-system-role.plugin.js +2 -43
  222. package/dist/core/common/plugins/mongoose-system-role.plugin.js.map +1 -1
  223. package/dist/core/common/plugins/mongoose-tenant.plugin.js +10 -70
  224. package/dist/core/common/plugins/mongoose-tenant.plugin.js.map +1 -1
  225. package/dist/core/common/scalars/upload.scalar.js +1 -1
  226. package/dist/core/common/scalars/upload.scalar.js.map +1 -1
  227. package/dist/core/common/services/core-cron-jobs.initializer.js +1 -1
  228. package/dist/core/common/services/core-cron-jobs.initializer.js.map +1 -1
  229. package/dist/core/common/services/core-cron-jobs.service.d.ts +1 -0
  230. package/dist/core/common/services/core-cron-jobs.service.js +23 -14
  231. package/dist/core/common/services/core-cron-jobs.service.js.map +1 -1
  232. package/dist/core/common/services/crud.service.d.ts +4 -1
  233. package/dist/core/common/services/crud.service.js +132 -23
  234. package/dist/core/common/services/crud.service.js.map +1 -1
  235. package/dist/core/common/services/model-doc.service.js +1 -1
  236. package/dist/core/common/services/model-doc.service.js.map +1 -1
  237. package/dist/core/common/services/module.service.d.ts +9 -2
  238. package/dist/core/common/services/module.service.js +51 -6
  239. package/dist/core/common/services/module.service.js.map +1 -1
  240. package/dist/core/common/types/field-selection.type.d.ts +1 -1
  241. package/dist/core/common/types/id.type.d.ts +4 -4
  242. package/dist/core/common/types/object-id-like.type.d.ts +3 -0
  243. package/dist/core/common/types/object-id-like.type.js +2 -0
  244. package/dist/core/common/types/object-id-like.type.js.map +1 -0
  245. package/dist/core/common/types/populate-config.type.d.ts +1 -1
  246. package/dist/core/common/types/string-or-object-id.type.d.ts +2 -2
  247. package/dist/core/modules/ai/core-ai.constants.d.ts +4 -0
  248. package/dist/core/modules/ai/core-ai.constants.js +4 -0
  249. package/dist/core/modules/ai/core-ai.constants.js.map +1 -1
  250. package/dist/core/modules/ai/core-ai.module.js +21 -17
  251. package/dist/core/modules/ai/core-ai.module.js.map +1 -1
  252. package/dist/core/modules/ai/models/core-ai-budget-limit.model.d.ts +2 -92
  253. package/dist/core/modules/ai/models/core-ai-budget-limit.model.js +1 -1
  254. package/dist/core/modules/ai/models/core-ai-budget-limit.model.js.map +1 -1
  255. package/dist/core/modules/ai/models/core-ai-connection-preference.model.d.ts +2 -87
  256. package/dist/core/modules/ai/models/core-ai-connection-preference.model.js +1 -1
  257. package/dist/core/modules/ai/models/core-ai-connection-preference.model.js.map +1 -1
  258. package/dist/core/modules/ai/models/core-ai-connection.model.d.ts +2 -177
  259. package/dist/core/modules/ai/models/core-ai-connection.model.js +1 -1
  260. package/dist/core/modules/ai/models/core-ai-connection.model.js.map +1 -1
  261. package/dist/core/modules/ai/models/core-ai-conversation.model.d.ts +2 -92
  262. package/dist/core/modules/ai/models/core-ai-conversation.model.js +3 -4
  263. package/dist/core/modules/ai/models/core-ai-conversation.model.js.map +1 -1
  264. package/dist/core/modules/ai/models/core-ai-interaction.model.d.ts +2 -120
  265. package/dist/core/modules/ai/models/core-ai-interaction.model.js +2 -3
  266. package/dist/core/modules/ai/models/core-ai-interaction.model.js.map +1 -1
  267. package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.d.ts +3 -0
  268. package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.js +21 -0
  269. package/dist/core/modules/ai/models/core-ai-mcp-oauth.models.js.map +1 -0
  270. package/dist/core/modules/ai/models/core-ai-mode.model.d.ts +2 -102
  271. package/dist/core/modules/ai/models/core-ai-mode.model.js +1 -1
  272. package/dist/core/modules/ai/models/core-ai-mode.model.js.map +1 -1
  273. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.d.ts +2 -97
  274. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js +1 -1
  275. package/dist/core/modules/ai/models/core-ai-prompt-hint.model.js.map +1 -1
  276. package/dist/core/modules/ai/models/core-ai-prompt.model.d.ts +2 -112
  277. package/dist/core/modules/ai/models/core-ai-prompt.model.js +1 -1
  278. package/dist/core/modules/ai/models/core-ai-prompt.model.js.map +1 -1
  279. package/dist/core/modules/ai/models/core-ai-slot.model.d.ts +2 -112
  280. package/dist/core/modules/ai/models/core-ai-slot.model.js +1 -1
  281. package/dist/core/modules/ai/models/core-ai-slot.model.js.map +1 -1
  282. package/dist/core/modules/ai/models/core-ai-tool-grant.model.d.ts +2 -97
  283. package/dist/core/modules/ai/models/core-ai-tool-grant.model.js +1 -1
  284. package/dist/core/modules/ai/models/core-ai-tool-grant.model.js.map +1 -1
  285. package/dist/core/modules/ai/models/core-ai-tool-policy.model.d.ts +2 -103
  286. package/dist/core/modules/ai/models/core-ai-tool-policy.model.js +1 -1
  287. package/dist/core/modules/ai/models/core-ai-tool-policy.model.js.map +1 -1
  288. package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +3 -1
  289. package/dist/core/modules/ai/services/core-ai-budget.service.js +15 -5
  290. package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -1
  291. package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +1 -1
  292. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +6 -10
  293. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -1
  294. package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +1 -1
  295. package/dist/core/modules/ai/services/core-ai-connection.service.js +20 -42
  296. package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -1
  297. package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +1 -1
  298. package/dist/core/modules/ai/services/core-ai-conversation.service.js +28 -29
  299. package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
  300. package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +1 -1
  301. package/dist/core/modules/ai/services/core-ai-interaction.service.js +3 -4
  302. package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -1
  303. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.d.ts +8 -0
  304. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js +70 -18
  305. package/dist/core/modules/ai/services/core-ai-mcp-oauth.service.js.map +1 -1
  306. package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +1 -1
  307. package/dist/core/modules/ai/services/core-ai-mode.service.js +3 -7
  308. package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -1
  309. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +8 -1
  310. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +32 -26
  311. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -1
  312. package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +1 -1
  313. package/dist/core/modules/ai/services/core-ai-prompt.service.js +10 -13
  314. package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -1
  315. package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +1 -1
  316. package/dist/core/modules/ai/services/core-ai-slot.service.js +14 -25
  317. package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -1
  318. package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +1 -1
  319. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +6 -18
  320. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -1
  321. package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +1 -1
  322. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +4 -8
  323. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -1
  324. package/dist/core/modules/api-token/core-api-token.model.js +1 -1
  325. package/dist/core/modules/api-token/core-api-token.model.js.map +1 -1
  326. package/dist/core/modules/api-token/core-api-token.module.js +3 -2
  327. package/dist/core/modules/api-token/core-api-token.module.js.map +1 -1
  328. package/dist/core/modules/api-token/core-api-token.service.d.ts +8 -2
  329. package/dist/core/modules/api-token/core-api-token.service.js +106 -39
  330. package/dist/core/modules/api-token/core-api-token.service.js.map +1 -1
  331. package/dist/core/modules/auth/core-auth.module.js +2 -0
  332. package/dist/core/modules/auth/core-auth.module.js.map +1 -1
  333. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +1 -2
  334. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -1
  335. package/dist/core/modules/auth/guards/role-guard.token.d.ts +1 -0
  336. package/dist/core/modules/auth/guards/role-guard.token.js +2 -0
  337. package/dist/core/modules/auth/guards/role-guard.token.js.map +1 -0
  338. package/dist/core/modules/auth/services/core-auth.service.js +4 -2
  339. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  340. package/dist/core/modules/better-auth/better-auth-sql.helper.d.ts +6 -0
  341. package/dist/core/modules/better-auth/better-auth-sql.helper.js +113 -0
  342. package/dist/core/modules/better-auth/better-auth-sql.helper.js.map +1 -0
  343. package/dist/core/modules/better-auth/better-auth-token.service.d.ts +3 -1
  344. package/dist/core/modules/better-auth/better-auth-token.service.js +15 -24
  345. package/dist/core/modules/better-auth/better-auth-token.service.js.map +1 -1
  346. package/dist/core/modules/better-auth/better-auth.config.d.ts +7 -0
  347. package/dist/core/modules/better-auth/better-auth.config.js +16 -5
  348. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  349. package/dist/core/modules/better-auth/better-auth.types.d.ts +1 -1
  350. package/dist/core/modules/better-auth/core-better-auth-api.middleware.d.ts +1 -0
  351. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js +6 -1
  352. package/dist/core/modules/better-auth/core-better-auth-api.middleware.js.map +1 -1
  353. package/dist/core/modules/better-auth/core-better-auth-challenge.service.js +30 -15
  354. package/dist/core/modules/better-auth/core-better-auth-challenge.service.js.map +1 -1
  355. package/dist/core/modules/better-auth/core-better-auth-mongo.users.d.ts +10 -0
  356. package/dist/core/modules/better-auth/core-better-auth-mongo.users.js +24 -0
  357. package/dist/core/modules/better-auth/core-better-auth-mongo.users.js.map +1 -0
  358. package/dist/core/modules/better-auth/core-better-auth-sql.registry.d.ts +3 -0
  359. package/dist/core/modules/better-auth/core-better-auth-sql.registry.js +8 -0
  360. package/dist/core/modules/better-auth/core-better-auth-sql.registry.js.map +1 -0
  361. package/dist/core/modules/better-auth/core-better-auth-sql.store.d.ts +71 -0
  362. package/dist/core/modules/better-auth/core-better-auth-sql.store.js +190 -0
  363. package/dist/core/modules/better-auth/core-better-auth-sql.store.js.map +1 -0
  364. package/dist/core/modules/better-auth/core-better-auth-user.mapper.d.ts +24 -1
  365. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js +308 -32
  366. package/dist/core/modules/better-auth/core-better-auth-user.mapper.js.map +1 -1
  367. package/dist/core/modules/better-auth/core-better-auth.module.d.ts +2 -0
  368. package/dist/core/modules/better-auth/core-better-auth.module.js +54 -32
  369. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
  370. package/dist/core/modules/better-auth/core-better-auth.service.d.ts +7 -2
  371. package/dist/core/modules/better-auth/core-better-auth.service.js +61 -9
  372. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
  373. package/dist/core/modules/file/core-file-info.model.d.ts +1 -2
  374. package/dist/core/modules/file/core-file-info.model.js +2 -2
  375. package/dist/core/modules/file/core-file-info.model.js.map +1 -1
  376. package/dist/core/modules/file/core-file.service.d.ts +5 -3
  377. package/dist/core/modules/file/core-file.service.js +16 -9
  378. package/dist/core/modules/file/core-file.service.js.map +1 -1
  379. package/dist/core/modules/file/file-metadata.helper.d.ts +1 -1
  380. package/dist/core/modules/file/file-metadata.helper.js +2 -2
  381. package/dist/core/modules/file/file-metadata.helper.js.map +1 -1
  382. package/dist/core/modules/file/file-metadata.models.d.ts +35 -0
  383. package/dist/core/modules/file/file-metadata.models.js +20 -0
  384. package/dist/core/modules/file/file-metadata.models.js.map +1 -0
  385. package/dist/core/modules/file/file-metadata.store.d.ts +6 -0
  386. package/dist/core/modules/file/file-metadata.store.js +77 -0
  387. package/dist/core/modules/file/file-metadata.store.js.map +1 -0
  388. package/dist/core/modules/file/file-storage.helper.d.ts +1 -0
  389. package/dist/core/modules/file/file-storage.helper.js +34 -0
  390. package/dist/core/modules/file/file-storage.helper.js.map +1 -1
  391. package/dist/core/modules/file/filesystem-file.helper.d.ts +1 -1
  392. package/dist/core/modules/file/filesystem-file.helper.js +4 -4
  393. package/dist/core/modules/file/filesystem-file.helper.js.map +1 -1
  394. package/dist/core/modules/file/s3-file.helper.d.ts +1 -1
  395. package/dist/core/modules/file/s3-file.helper.js +5 -5
  396. package/dist/core/modules/file/s3-file.helper.js.map +1 -1
  397. package/dist/core/modules/health-check/core-health-check.module.js +12 -2
  398. package/dist/core/modules/health-check/core-health-check.module.js.map +1 -1
  399. package/dist/core/modules/health-check/core-health-check.service.d.ts +4 -3
  400. package/dist/core/modules/health-check/core-health-check.service.js +26 -5
  401. package/dist/core/modules/health-check/core-health-check.service.js.map +1 -1
  402. package/dist/core/modules/hub/core-hub.controller.d.ts +1 -0
  403. package/dist/core/modules/hub/core-hub.controller.js +10 -0
  404. package/dist/core/modules/hub/core-hub.controller.js.map +1 -1
  405. package/dist/core/modules/hub/core-hub.service.js +1 -1
  406. package/dist/core/modules/hub/core-hub.service.js.map +1 -1
  407. package/dist/core/modules/hub/helpers/hub-client-js.helper.js +23 -0
  408. package/dist/core/modules/hub/helpers/hub-client-js.helper.js.map +1 -1
  409. package/dist/core/modules/hub/hub-action-messages.d.ts +2 -0
  410. package/dist/core/modules/hub/hub-action-messages.js +2 -0
  411. package/dist/core/modules/hub/hub-action-messages.js.map +1 -1
  412. package/dist/core/modules/hub/hub-nav.js +1 -0
  413. package/dist/core/modules/hub/hub-nav.js.map +1 -1
  414. package/dist/core/modules/hub/interfaces/hub-panels.interface.d.ts +17 -1
  415. package/dist/core/modules/hub/services/core-hub-db.service.d.ts +6 -1
  416. package/dist/core/modules/hub/services/core-hub-db.service.js +16 -14
  417. package/dist/core/modules/hub/services/core-hub-db.service.js.map +1 -1
  418. package/dist/core/modules/hub/services/core-hub-migrations.service.d.ts +5 -0
  419. package/dist/core/modules/hub/services/core-hub-migrations.service.js +74 -1
  420. package/dist/core/modules/hub/services/core-hub-migrations.service.js.map +1 -1
  421. package/dist/core/modules/hub/services/core-hub-sources.service.d.ts +2 -1
  422. package/dist/core/modules/hub/services/core-hub-sources.service.js +32 -0
  423. package/dist/core/modules/hub/services/core-hub-sources.service.js.map +1 -1
  424. package/dist/core/modules/hub/services/hub-query-profiler.service.js +1 -1
  425. package/dist/core/modules/hub/services/hub-query-profiler.service.js.map +1 -1
  426. package/dist/core/modules/migrate/cli/migrate-cli.d.ts +2 -0
  427. package/dist/core/modules/migrate/cli/migrate-cli.js +35 -1
  428. package/dist/core/modules/migrate/cli/migrate-cli.js.map +1 -1
  429. package/dist/core/modules/migrate/index.d.ts +3 -0
  430. package/dist/core/modules/migrate/index.js +3 -0
  431. package/dist/core/modules/migrate/index.js.map +1 -1
  432. package/dist/core/modules/migrate/migration-runner.d.ts +2 -2
  433. package/dist/core/modules/migrate/migration-runner.js.map +1 -1
  434. package/dist/core/modules/migrate/migration-state-store.interface.d.ts +16 -0
  435. package/dist/core/modules/migrate/migration-state-store.interface.js +2 -0
  436. package/dist/core/modules/migrate/migration-state-store.interface.js.map +1 -0
  437. package/dist/core/modules/migrate/migration.helper.d.ts +3 -2
  438. package/dist/core/modules/migrate/migration.helper.js +21 -6
  439. package/dist/core/modules/migrate/migration.helper.js.map +1 -1
  440. package/dist/core/modules/migrate/mongo-state-store.d.ts +5 -12
  441. package/dist/core/modules/migrate/mongo-state-store.js +30 -24
  442. package/dist/core/modules/migrate/mongo-state-store.js.map +1 -1
  443. package/dist/core/modules/migrate/sql-migration.helper.d.ts +4 -0
  444. package/dist/core/modules/migrate/sql-migration.helper.js +34 -0
  445. package/dist/core/modules/migrate/sql-migration.helper.js.map +1 -0
  446. package/dist/core/modules/migrate/sql-state-store.d.ts +24 -0
  447. package/dist/core/modules/migrate/sql-state-store.js +129 -0
  448. package/dist/core/modules/migrate/sql-state-store.js.map +1 -0
  449. package/dist/core/modules/system-setup/core-system-setup.service.d.ts +8 -0
  450. package/dist/core/modules/system-setup/core-system-setup.service.js +41 -25
  451. package/dist/core/modules/system-setup/core-system-setup.service.js.map +1 -1
  452. package/dist/core/modules/tenant/core-tenant-member.model.js +1 -1
  453. package/dist/core/modules/tenant/core-tenant-member.model.js.map +1 -1
  454. package/dist/core/modules/tenant/core-tenant-member.store.d.ts +2 -0
  455. package/dist/core/modules/tenant/core-tenant-member.store.js +6 -0
  456. package/dist/core/modules/tenant/core-tenant-member.store.js.map +1 -0
  457. package/dist/core/modules/tenant/core-tenant.guard.d.ts +8 -3
  458. package/dist/core/modules/tenant/core-tenant.guard.js +57 -28
  459. package/dist/core/modules/tenant/core-tenant.guard.js.map +1 -1
  460. package/dist/core/modules/tenant/core-tenant.module.js +3 -2
  461. package/dist/core/modules/tenant/core-tenant.module.js.map +1 -1
  462. package/dist/core/modules/tenant/core-tenant.service.d.ts +3 -1
  463. package/dist/core/modules/tenant/core-tenant.service.js +48 -28
  464. package/dist/core/modules/tenant/core-tenant.service.js.map +1 -1
  465. package/dist/core/modules/tus/core-tus.service.d.ts +1 -1
  466. package/dist/core/modules/tus/core-tus.service.js +8 -7
  467. package/dist/core/modules/tus/core-tus.service.js.map +1 -1
  468. package/dist/core/modules/tus/tus.module.js +1 -1
  469. package/dist/core/modules/tus/tus.module.js.map +1 -1
  470. package/dist/core/modules/user/core-user.model.d.ts +1 -1
  471. package/dist/core/modules/user/core-user.model.js +1 -1
  472. package/dist/core/modules/user/core-user.model.js.map +1 -1
  473. package/dist/core/modules/user/core-user.service.d.ts +3 -1
  474. package/dist/core/modules/user/core-user.service.js +71 -16
  475. package/dist/core/modules/user/core-user.service.js.map +1 -1
  476. package/dist/core.module.js +39 -5
  477. package/dist/core.module.js.map +1 -1
  478. package/dist/index.d.ts +26 -0
  479. package/dist/index.js +26 -0
  480. package/dist/index.js.map +1 -1
  481. package/dist/server/common/models/persistence.model.d.ts +1 -1
  482. package/dist/server/common/models/persistence.model.js +3 -3
  483. package/dist/server/common/models/persistence.model.js.map +1 -1
  484. package/dist/server/modules/file/file-info.model.d.ts +1 -77
  485. package/dist/server/modules/file/file-info.model.js +1 -1
  486. package/dist/server/modules/file/file-info.model.js.map +1 -1
  487. package/dist/server/modules/file/file.service.js +1 -1
  488. package/dist/server/modules/file/file.service.js.map +1 -1
  489. package/dist/server/modules/user/user.model.d.ts +2 -186
  490. package/dist/server/modules/user/user.model.js +4 -5
  491. package/dist/server/modules/user/user.model.js.map +1 -1
  492. package/dist/server/modules/user/user.module.js +4 -3
  493. package/dist/server/modules/user/user.module.js.map +1 -1
  494. package/dist/server/modules/user/user.service.d.ts +1 -1
  495. package/dist/server/modules/user/user.service.js +5 -8
  496. package/dist/server/modules/user/user.service.js.map +1 -1
  497. package/dist/test/test.helper.js +2 -2
  498. package/dist/test/test.helper.js.map +1 -1
  499. package/dist/types/graphql-upload.d.ts +10 -7
  500. package/docs/REQUEST-LIFECYCLE.md +6 -3
  501. package/docs/choosing-a-database.md +107 -0
  502. package/docs/native-driver-security.md +29 -0
  503. package/docs/security-overrides.md +15 -6
  504. package/migration-guides/12.0.x-to-12.1.x.md +255 -0
  505. package/package.json +75 -29
  506. package/src/core/common/decorators/unified-field.decorator.ts +11 -1
  507. package/src/core/common/filters/mongoose-cast-error.filter.ts +12 -6
  508. package/src/core/common/helpers/db.helper.ts +40 -25
  509. package/src/core/common/helpers/decorator.helper.ts +1 -1
  510. package/src/core/common/helpers/filter.helper.ts +2 -1
  511. package/src/core/common/helpers/gridfs.helper.ts +28 -9
  512. package/src/core/common/helpers/id.helper.ts +21 -4
  513. package/src/core/common/helpers/model.helper.ts +5 -6
  514. package/src/core/common/helpers/service.helper.ts +3 -3
  515. package/src/core/common/interfaces/server-options.interface.ts +118 -10
  516. package/src/core/common/interfaces/service-options.interface.ts +2 -2
  517. package/src/core/common/models/core-persistence.model.ts +3 -3
  518. package/src/core/common/persistence/core-persistence.lifecycle.ts +47 -0
  519. package/src/core/common/persistence/core-persistence.module.ts +109 -0
  520. package/src/core/common/persistence/data-source.config.ts +271 -0
  521. package/src/core/common/persistence/data-source.runtime.ts +351 -0
  522. package/src/core/common/persistence/data-store.interface.ts +155 -0
  523. package/src/core/common/persistence/expiry-sweep.ts +105 -0
  524. package/src/core/common/persistence/id-format.ts +43 -0
  525. package/src/core/common/persistence/infrastructure-locks.ts +66 -0
  526. package/src/core/common/persistence/inject-store.decorator.ts +16 -0
  527. package/src/core/common/persistence/lock-store.interface.ts +17 -0
  528. package/src/core/common/persistence/model-descriptor.interface.ts +90 -0
  529. package/src/core/common/persistence/model-metadata.registry.ts +285 -0
  530. package/src/core/common/persistence/mongo/collection-name.ts +87 -0
  531. package/src/core/common/persistence/mongo/declared-schema.view.ts +378 -0
  532. package/src/core/common/persistence/mongo/hex-object-id.ts +75 -0
  533. package/src/core/common/persistence/mongo/model-declarations.ts +135 -0
  534. package/src/core/common/persistence/mongo/mongo-packages.ts +130 -0
  535. package/src/core/common/persistence/mongo/mongoose-compat.ts +129 -0
  536. package/src/core/common/persistence/mongo/no-mongo-connection.module.ts +18 -0
  537. package/src/core/common/persistence/mongo-lock-store.ts +121 -0
  538. package/src/core/common/persistence/mongoose-data-store.ts +232 -0
  539. package/src/core/common/persistence/neutral-populate.ts +98 -0
  540. package/src/core/common/persistence/persisted-model.decorator.ts +61 -0
  541. package/src/core/common/persistence/persistence-runtime.registry.ts +152 -0
  542. package/src/core/common/persistence/persistence.tokens.ts +9 -0
  543. package/src/core/common/persistence/policies/audit.policy.ts +80 -0
  544. package/src/core/common/persistence/policies/password.policy.ts +69 -0
  545. package/src/core/common/persistence/policies/role-guard.policy.ts +74 -0
  546. package/src/core/common/persistence/policies/system-role.policy.ts +90 -0
  547. package/src/core/common/persistence/policies/tenant.policy.ts +245 -0
  548. package/src/core/common/persistence/routed-model.guard.ts +107 -0
  549. package/src/core/common/persistence/sql/mysql/mysql-data-store.ts +503 -0
  550. package/src/core/common/persistence/sql/mysql/mysql-executor.ts +281 -0
  551. package/src/core/common/persistence/sql/mysql/mysql-lock-store.ts +87 -0
  552. package/src/core/common/persistence/sql/mysql/mysql-schema.compiler.ts +424 -0
  553. package/src/core/common/persistence/sql/mysql/mysql-schema.migrator.ts +453 -0
  554. package/src/core/common/persistence/sql/mysql/mysql-session.ts +131 -0
  555. package/src/core/common/persistence/sql/mysql/mysql-update.compiler.ts +379 -0
  556. package/src/core/common/persistence/sql/mysql/mysql-where.compiler.ts +686 -0
  557. package/src/core/common/persistence/sql/postgres/postgres-lock-store.ts +76 -0
  558. package/src/core/common/persistence/sql/postgres/postgres-schema.compiler.ts +328 -0
  559. package/src/core/common/persistence/sql/postgres/postgres-schema.migrator.ts +448 -0
  560. package/src/core/common/persistence/sql/postgres/postgres-update.compiler.ts +310 -0
  561. package/src/core/common/persistence/sql/postgres/postgres-where.compiler.ts +638 -0
  562. package/src/core/common/persistence/sql/sql-cast.ts +227 -0
  563. package/src/core/common/persistence/sql/sql-data-store.ts +762 -0
  564. package/src/core/common/persistence/sql/sql-dialect.ts +85 -0
  565. package/src/core/common/persistence/sql/sql-errors.ts +49 -0
  566. package/src/core/common/persistence/sql/sql-executor.factory.ts +282 -0
  567. package/src/core/common/persistence/sql/sql-executor.interface.ts +57 -0
  568. package/src/core/common/persistence/sql/sql-naming.ts +133 -0
  569. package/src/core/common/persistence/sql/sql-schema.shared.ts +105 -0
  570. package/src/core/common/persistence/sql/sql-session.ts +158 -0
  571. package/src/core/common/persistence/sql/where-shared.ts +118 -0
  572. package/src/core/common/persistence/store-guards.ts +73 -0
  573. package/src/core/common/persistence/store-upsert.ts +36 -0
  574. package/src/core/common/persistence/unavailable-store.ts +63 -0
  575. package/src/core/common/persistence/unsupported-capability.error.ts +7 -0
  576. package/src/core/common/plugins/mongoose-audit-fields.plugin.ts +33 -74
  577. package/src/core/common/plugins/mongoose-id.plugin.ts +9 -0
  578. package/src/core/common/plugins/mongoose-password.plugin.ts +6 -62
  579. package/src/core/common/plugins/mongoose-role-guard.plugin.ts +11 -63
  580. package/src/core/common/plugins/mongoose-system-role.plugin.ts +7 -78
  581. package/src/core/common/plugins/mongoose-tenant.plugin.ts +23 -144
  582. package/src/core/common/scalars/upload.scalar.ts +8 -3
  583. package/src/core/common/services/core-cron-jobs.initializer.ts +1 -1
  584. package/src/core/common/services/core-cron-jobs.service.ts +33 -22
  585. package/src/core/common/services/crud.service.ts +166 -35
  586. package/src/core/common/services/model-doc.service.ts +1 -1
  587. package/src/core/common/services/module.service.ts +78 -6
  588. package/src/core/common/types/field-selection.type.ts +1 -1
  589. package/src/core/common/types/id.type.ts +2 -2
  590. package/src/core/common/types/object-id-like.type.ts +11 -0
  591. package/src/core/common/types/populate-config.type.ts +1 -1
  592. package/src/core/common/types/string-or-object-id.type.ts +2 -2
  593. package/src/core/modules/ai/README.md +15 -2
  594. package/src/core/modules/ai/core-ai.constants.ts +10 -0
  595. package/src/core/modules/ai/core-ai.module.ts +32 -17
  596. package/src/core/modules/ai/models/core-ai-budget-limit.model.ts +2 -2
  597. package/src/core/modules/ai/models/core-ai-connection-preference.model.ts +2 -2
  598. package/src/core/modules/ai/models/core-ai-connection.model.ts +2 -2
  599. package/src/core/modules/ai/models/core-ai-conversation.model.ts +8 -4
  600. package/src/core/modules/ai/models/core-ai-interaction.model.ts +3 -3
  601. package/src/core/modules/ai/models/core-ai-mcp-oauth.models.ts +46 -0
  602. package/src/core/modules/ai/models/core-ai-mode.model.ts +2 -2
  603. package/src/core/modules/ai/models/core-ai-prompt-hint.model.ts +2 -2
  604. package/src/core/modules/ai/models/core-ai-prompt.model.ts +2 -2
  605. package/src/core/modules/ai/models/core-ai-slot.model.ts +2 -2
  606. package/src/core/modules/ai/models/core-ai-tool-grant.model.ts +2 -2
  607. package/src/core/modules/ai/models/core-ai-tool-policy.model.ts +2 -2
  608. package/src/core/modules/ai/services/core-ai-budget.service.ts +22 -4
  609. package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +6 -13
  610. package/src/core/modules/ai/services/core-ai-connection.service.ts +34 -44
  611. package/src/core/modules/ai/services/core-ai-conversation.service.ts +31 -29
  612. package/src/core/modules/ai/services/core-ai-interaction.service.ts +3 -3
  613. package/src/core/modules/ai/services/core-ai-mcp-oauth.service.ts +93 -20
  614. package/src/core/modules/ai/services/core-ai-mode.service.ts +3 -6
  615. package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +43 -26
  616. package/src/core/modules/ai/services/core-ai-prompt.service.ts +15 -12
  617. package/src/core/modules/ai/services/core-ai-slot.service.ts +20 -24
  618. package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +17 -27
  619. package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +7 -10
  620. package/src/core/modules/api-token/core-api-token.model.ts +1 -1
  621. package/src/core/modules/api-token/core-api-token.module.ts +4 -2
  622. package/src/core/modules/api-token/core-api-token.service.ts +118 -43
  623. package/src/core/modules/auth/core-auth.module.ts +2 -0
  624. package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +4 -3
  625. package/src/core/modules/auth/guards/role-guard.token.ts +7 -0
  626. package/src/core/modules/auth/services/core-auth.service.ts +16 -2
  627. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +1 -1
  628. package/src/core/modules/better-auth/README.md +10 -1
  629. package/src/core/modules/better-auth/better-auth-sql.helper.ts +191 -0
  630. package/src/core/modules/better-auth/better-auth-token.service.ts +26 -35
  631. package/src/core/modules/better-auth/better-auth.config.ts +43 -7
  632. package/src/core/modules/better-auth/better-auth.types.ts +1 -1
  633. package/src/core/modules/better-auth/core-better-auth-api.middleware.ts +13 -1
  634. package/src/core/modules/better-auth/core-better-auth-challenge.service.ts +36 -18
  635. package/src/core/modules/better-auth/core-better-auth-mongo.users.ts +35 -0
  636. package/src/core/modules/better-auth/core-better-auth-sql.registry.ts +20 -0
  637. package/src/core/modules/better-auth/core-better-auth-sql.store.ts +309 -0
  638. package/src/core/modules/better-auth/core-better-auth-user.mapper.ts +418 -40
  639. package/src/core/modules/better-auth/core-better-auth.module.ts +71 -35
  640. package/src/core/modules/better-auth/core-better-auth.service.ts +81 -12
  641. package/src/core/modules/file/README.md +16 -3
  642. package/src/core/modules/file/core-file-info.model.ts +2 -2
  643. package/src/core/modules/file/core-file.service.ts +27 -18
  644. package/src/core/modules/file/file-metadata.helper.ts +7 -3
  645. package/src/core/modules/file/file-metadata.models.ts +44 -0
  646. package/src/core/modules/file/file-metadata.store.ts +109 -0
  647. package/src/core/modules/file/file-storage.helper.ts +47 -2
  648. package/src/core/modules/file/filesystem-file.helper.ts +11 -8
  649. package/src/core/modules/file/s3-file.helper.ts +11 -7
  650. package/src/core/modules/health-check/core-health-check.module.ts +16 -2
  651. package/src/core/modules/health-check/core-health-check.service.ts +25 -3
  652. package/src/core/modules/hub/README.md +20 -11
  653. package/src/core/modules/hub/core-hub.controller.ts +5 -0
  654. package/src/core/modules/hub/core-hub.service.ts +1 -1
  655. package/src/core/modules/hub/helpers/hub-client-js.helper.ts +23 -0
  656. package/src/core/modules/hub/hub-action-messages.ts +6 -0
  657. package/src/core/modules/hub/hub-nav.ts +1 -0
  658. package/src/core/modules/hub/interfaces/hub-panels.interface.ts +8 -1
  659. package/src/core/modules/hub/services/core-hub-db.service.ts +35 -17
  660. package/src/core/modules/hub/services/core-hub-migrations.service.ts +96 -2
  661. package/src/core/modules/hub/services/core-hub-sources.service.ts +47 -1
  662. package/src/core/modules/hub/services/hub-query-profiler.service.ts +1 -1
  663. package/src/core/modules/migrate/README.md +54 -0
  664. package/src/core/modules/migrate/cli/migrate-cli.ts +44 -3
  665. package/src/core/modules/migrate/index.ts +3 -0
  666. package/src/core/modules/migrate/migration-runner.ts +3 -2
  667. package/src/core/modules/migrate/migration-state-store.interface.ts +24 -0
  668. package/src/core/modules/migrate/migration.helper.ts +35 -10
  669. package/src/core/modules/migrate/mongo-state-store.ts +64 -65
  670. package/src/core/modules/migrate/sql-migration.helper.ts +48 -0
  671. package/src/core/modules/migrate/sql-state-store.ts +198 -0
  672. package/src/core/modules/system-setup/README.md +14 -2
  673. package/src/core/modules/system-setup/core-system-setup.service.ts +77 -45
  674. package/src/core/modules/tenant/README.md +9 -2
  675. package/src/core/modules/tenant/core-tenant-member.model.ts +1 -1
  676. package/src/core/modules/tenant/core-tenant-member.store.ts +13 -0
  677. package/src/core/modules/tenant/core-tenant.guard.ts +77 -24
  678. package/src/core/modules/tenant/core-tenant.module.ts +6 -3
  679. package/src/core/modules/tenant/core-tenant.service.ts +59 -42
  680. package/src/core/modules/tus/core-tus.service.ts +11 -12
  681. package/src/core/modules/tus/tus.module.ts +1 -1
  682. package/src/core/modules/user/core-user.model.ts +2 -2
  683. package/src/core/modules/user/core-user.service.ts +98 -20
  684. package/src/core.module.ts +60 -5
  685. package/src/index.ts +26 -0
  686. package/src/server/common/models/persistence.model.ts +4 -4
  687. package/src/server/modules/file/file-info.model.ts +1 -1
  688. package/src/server/modules/file/file.service.ts +1 -1
  689. package/src/server/modules/user/user.model.ts +10 -5
  690. package/src/server/modules/user/user.module.ts +9 -3
  691. package/src/server/modules/user/user.service.ts +9 -11
  692. package/src/test/test.helper.ts +2 -2
  693. package/src/types/graphql-upload.d.ts +10 -7
@@ -1,7 +1,6 @@
1
1
  import { Inject, Injectable, Logger, Optional } from '@nestjs/common';
2
- import { InjectConnection } from '@nestjs/mongoose';
3
- import * as mongo from 'mongodb';
4
- import { type Connection, Types } from 'mongoose';
2
+ import type * as mongo from 'mongodb';
3
+ import type { Connection } from 'mongoose';
5
4
 
6
5
  import { ConfigService } from '../../../common/services/config.service.js';
7
6
  import { CoreS3Service } from '../../../common/services/core-s3.service.js';
@@ -11,6 +10,7 @@ import {
11
10
  FILESYSTEM_FILES_COLLECTION,
12
11
  FilesystemFileHelper,
13
12
  } from '../../file/filesystem-file.helper.js';
13
+ import { fileMetadataCollection } from '../../file/file-metadata.store.js';
14
14
  import { S3_FILES_COLLECTION, S3FileHelper } from '../../file/s3-file.helper.js';
15
15
  import { HubActionMessage } from '../hub-action-messages.js';
16
16
  import { HUB_CONFIG } from '../hub.constants.js';
@@ -24,6 +24,12 @@ import {
24
24
  HubUnavailable,
25
25
  } from '../interfaces/hub-panels.interface.js';
26
26
  import type { ResolvedHubConfig } from '../interfaces/hub-config.interface.js';
27
+ import {
28
+ createGridFsBucket,
29
+ InjectConnection,
30
+ isValidObjectId,
31
+ newObjectId,
32
+ } from '../../../common/persistence/mongo/mongoose-compat.js';
27
33
 
28
34
  /**
29
35
  * Read-only MongoDB introspection for the DB, Models/ERD and Files panels.
@@ -123,10 +129,10 @@ export class CoreHubDbService {
123
129
  if (!db) {
124
130
  throw new Error(HubActionMessage.mongoUnavailable);
125
131
  }
126
- if (!Types.ObjectId.isValid(id)) {
132
+ if (!isValidObjectId(id)) {
127
133
  throw new Error(HubActionMessage.invalidFileId);
128
134
  }
129
- const objectId = new Types.ObjectId(id);
135
+ const objectId = newObjectId(id);
130
136
 
131
137
  // Same probe order as `CoreFileService.deleteFile()`: S3, then filesystem, then GridFS as the
132
138
  // fallthrough. Keeping the two in step matters — a Hub that resolved a file differently from the
@@ -134,7 +140,7 @@ export class CoreHubDbService {
134
140
  let store: HubFileStore | undefined;
135
141
  let doc: any;
136
142
  for (const candidate of this.fileStores(bucket)) {
137
- const [found] = await db.collection(candidate.collection).find({ _id: objectId }, { limit: 1 }).toArray();
143
+ const [found] = await this.fileCollection(candidate).find({ _id: objectId }, { limit: 1 }).toArray();
138
144
  if (found) {
139
145
  doc = found;
140
146
  store = candidate.store;
@@ -150,7 +156,11 @@ export class CoreHubDbService {
150
156
 
151
157
  switch (store) {
152
158
  case 'filesystem': {
153
- await FilesystemFileHelper.deleteFile(this.filesystemDir, db.collection(FILESYSTEM_FILES_COLLECTION), objectId);
159
+ await FilesystemFileHelper.deleteFile(
160
+ this.filesystemDir,
161
+ fileMetadataCollection(this.connection, 'filesystem'),
162
+ objectId,
163
+ );
154
164
  break;
155
165
  }
156
166
  case 's3': {
@@ -158,11 +168,11 @@ export class CoreHubDbService {
158
168
  if (!this.s3Service?.enabled) {
159
169
  throw new Error(HubActionMessage.s3Unavailable);
160
170
  }
161
- await S3FileHelper.deleteFile(this.s3Service, db.collection(S3_FILES_COLLECTION), objectId);
171
+ await S3FileHelper.deleteFile(this.s3Service, fileMetadataCollection(this.connection, 's3'), objectId);
162
172
  break;
163
173
  }
164
174
  default: {
165
- const gridFs = new mongo.GridFSBucket(db as unknown as mongo.Db, { bucketName: bucket });
175
+ const gridFs = createGridFsBucket(db as unknown as mongo.Db, { bucketName: bucket });
166
176
  await gridFs.delete(objectId as unknown as mongo.ObjectId);
167
177
  }
168
178
  }
@@ -173,9 +183,9 @@ export class CoreHubDbService {
173
183
  /**
174
184
  * File inventory across ALL THREE metadata stores.
175
185
  *
176
- * Metadata always lives in MongoDB whichever store holds the bytes (`fs.files` / `s3-files` /
177
- * `filesystem-files`), so one connection can see everything — which is exactly what
178
- * `CoreFileService.findFileInfo()` does, and what this panel now mirrors.
186
+ * Metadata is queryable whichever store holds the bytes (`fs.files` / `s3-files` /
187
+ * `filesystem-files`, the latter two as tables when `database` routes them to a SQL source), so the
188
+ * panel reads all three the way `CoreFileService.findFileInfo()` does (`fileCollection()`).
179
189
  *
180
190
  * It used to read `fs.files` alone. Under `file.storage: 's3'` or `'filesystem'` that made the
181
191
  * panel report **0 files** — not "this panel does not cover your driver", but a confident wrong
@@ -209,11 +219,9 @@ export class CoreHubDbService {
209
219
 
210
220
  for (const source of this.fileStores(bucket)) {
211
221
  try {
212
- const docs = await db
213
- .collection(source.collection)
214
- .find({}, { limit: window, sort: { uploadDate: -1 } })
215
- .toArray();
216
- const count = await db.collection(source.collection).countDocuments();
222
+ const collection = this.fileCollection(source);
223
+ const docs = await collection.find({}, { limit: window, sort: { uploadDate: -1 } }).toArray();
224
+ const count = await collection.countDocuments();
217
225
  stores.push({ collection: source.collection, count, store: source.store });
218
226
  for (const doc of docs) {
219
227
  rows.push({
@@ -255,6 +263,16 @@ export class CoreHubDbService {
255
263
  * GridFS is last because it is the fallthrough: its collection name depends on the bucket, and a
256
264
  * document there carries no `storage` marker to identify it by.
257
265
  */
266
+ /**
267
+ * The metadata of one store as `CoreFileService` reads it: S3 and filesystem metadata follow `database` to a SQL
268
+ * table when their model is routed there; GridFS keeps `<bucket>.files` in MongoDB
269
+ */
270
+ protected fileCollection(source: { collection: string; store: HubFileStore }): mongo.Collection<any> {
271
+ return source.store === 'gridfs'
272
+ ? this.connection.db.collection(source.collection)
273
+ : fileMetadataCollection(this.connection, source.store);
274
+ }
275
+
258
276
  protected fileStores(bucket: string): { collection: string; store: HubFileStore }[] {
259
277
  return [
260
278
  { collection: S3_FILES_COLLECTION, store: 's3' },
@@ -1,12 +1,15 @@
1
1
  import { Inject, Injectable, Logger, Optional } from '@nestjs/common';
2
- import { InjectConnection } from '@nestjs/mongoose';
2
+ import { InjectConnection } from '../../../common/persistence/mongo/mongoose-compat.js';
3
3
  import { readdir } from 'fs/promises';
4
4
  import type { Connection } from 'mongoose';
5
5
  import { resolve } from 'path';
6
6
 
7
7
  import { ConfigService } from '../../../common/services/config.service.js';
8
8
  import { DEFAULT_MIGRATION_FILE_PATTERN, MigrationRunner } from '../../migrate/migration-runner.js';
9
+ import type { DatabaseSqlEngine } from '../../../common/interfaces/server-options.interface.js';
10
+ import { getPersistenceRuntime } from '../../../common/persistence/persistence-runtime.registry.js';
9
11
  import { MongoStateStore } from '../../migrate/mongo-state-store.js';
12
+ import { SqlStateStore } from '../../migrate/sql-state-store.js';
10
13
  import { HubActionMessage } from '../hub-action-messages.js';
11
14
  import { HUB_CONFIG } from '../hub.constants.js';
12
15
  import { HubMigrationsData, HubUnavailable } from '../interfaces/hub-panels.interface.js';
@@ -31,6 +34,7 @@ export class CoreHubMigrationsService {
31
34
 
32
35
  /** Run all pending migrations. Returns the titles that were applied. */
33
36
  async runPending(): Promise<{ ran: string[] }> {
37
+ await this.assertSingleMigrationState();
34
38
  const runner = this.buildRunner();
35
39
  const before = new Set(((await this.getStatus()) as HubMigrationsData).completed ?? []);
36
40
  await runner.up();
@@ -40,6 +44,7 @@ export class CoreHubMigrationsService {
40
44
 
41
45
  /** Roll back the most recently applied migration. Returns the title that was reverted. */
42
46
  async rollbackLast(): Promise<{ rolledBack?: string }> {
47
+ await this.assertSingleMigrationState();
43
48
  const before = ((await this.getStatus()) as HubMigrationsData).completed ?? [];
44
49
  const runner = this.buildRunner();
45
50
  await runner.down();
@@ -47,11 +52,18 @@ export class CoreHubMigrationsService {
47
52
  return { rolledBack: before.find((title) => !after.has(title)) };
48
53
  }
49
54
 
50
- /** Build a MigrationRunner from the hub config + the configured Mongo URI. */
55
+ /** Build a MigrationRunner from the hub config + the configured Mongo URI (or the SQL default source's owner). */
51
56
  protected buildRunner(): MigrationRunner {
52
57
  if (this.config.migrations === false) {
53
58
  throw new Error(HubActionMessage.migrationsDisabled);
54
59
  }
60
+ const sqlStore = this.sqlStateStore();
61
+ if (sqlStore) {
62
+ return new MigrationRunner({
63
+ migrationsDirectory: resolve(process.cwd(), this.config.migrations.dir),
64
+ stateStore: sqlStore,
65
+ });
66
+ }
55
67
  const uri = this.configService.getFastButReadOnly<string>('mongoose.uri');
56
68
  if (!uri) {
57
69
  throw new Error(HubActionMessage.mongoUriMissing);
@@ -66,11 +78,93 @@ export class CoreHubMigrationsService {
66
78
  });
67
79
  }
68
80
 
81
+ /**
82
+ * The migration state store when the default source is a SQL database: the framework keeps the state there
83
+ * (`lt_migrations`), readable and writable by the table owner only. Throws without `database.ownerUrl`.
84
+ */
85
+ protected sqlStateStore(): SqlStateStore | undefined {
86
+ const source = getPersistenceRuntime()?.defaultSqlSource();
87
+ if (!source) {
88
+ return undefined;
89
+ }
90
+ if (!source.ownerUrl) {
91
+ throw new Error(HubActionMessage.sqlOwnerMissing);
92
+ }
93
+ return new SqlStateStore({ engine: source.engine as DatabaseSqlEngine, url: source.ownerUrl });
94
+ }
95
+
96
+ /**
97
+ * Refuse to run or roll back while {@link migrationStateLeftInMongo} — the Hub would apply, against live data, every
98
+ * migration the project's own runs recorded in MongoDB.
99
+ */
100
+ protected async assertSingleMigrationState(): Promise<void> {
101
+ const sqlStore = this.sqlStateStore();
102
+ if (!sqlStore) {
103
+ return;
104
+ }
105
+ const completed = ((await sqlStore.loadAsync()).migrations ?? []).map((migration) => migration.title);
106
+ if (await this.migrationStateLeftInMongo(completed)) {
107
+ throw new Error(this.migrationStateInMongoMessage());
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Whether the project still records its migrations in MongoDB although the default source is a SQL database.
113
+ *
114
+ * The state of a SQL default source belongs in `lt_migrations`, but only `migrations-utils/migrate.js` decides where
115
+ * it actually goes: one that still passes the MongoDB URI to `createMigrationStore()` writes the MongoDB collection,
116
+ * and the empty table would show every applied migration as pending. Answered from the data, never guessed: an empty
117
+ * table next to a MongoDB collection that lists applied migrations. A MongoDB read that fails throws, so the panel
118
+ * never offers a run it could not rule out.
119
+ */
120
+ protected async migrationStateLeftInMongo(sqlCompleted: string[]): Promise<boolean> {
121
+ if (sqlCompleted.length || this.config.migrations === false) {
122
+ return false;
123
+ }
124
+ const db = this.connection?.db;
125
+ if (!db) {
126
+ return false;
127
+ }
128
+ const [stateDoc] = await db.collection(this.config.migrations.collectionName).find({}).limit(1).toArray();
129
+ return (stateDoc?.migrations ?? []).length > 0;
130
+ }
131
+
132
+ protected migrationStateInMongoMessage(): string {
133
+ return HubActionMessage.migrationStateInMongo(
134
+ this.config.migrations === false ? 'migrations' : this.config.migrations.collectionName,
135
+ );
136
+ }
137
+
69
138
  /** Completed + pending migrations. */
70
139
  async getStatus(): Promise<HubMigrationsData | HubUnavailable> {
71
140
  if (this.config.migrations === false) {
72
141
  return { available: false, hint: 'The migrations panel is disabled.' };
73
142
  }
143
+ let sqlStore: SqlStateStore | undefined;
144
+ try {
145
+ sqlStore = this.sqlStateStore();
146
+ } catch (error) {
147
+ return { available: false, hint: error instanceof Error ? error.message : String(error) };
148
+ }
149
+ if (sqlStore) {
150
+ let state: { lastRun?: string; migrations?: { title: string }[] } = {};
151
+ try {
152
+ state = await sqlStore.loadAsync();
153
+ } catch (error) {
154
+ this.logger.warn(`Failed to read migration state: ${error instanceof Error ? error.message : String(error)}`);
155
+ }
156
+ const completed = (state.migrations ?? []).map((migration) => migration.title);
157
+ try {
158
+ if (await this.migrationStateLeftInMongo(completed)) {
159
+ return { available: false, hint: this.migrationStateInMongoMessage() };
160
+ }
161
+ } catch (error) {
162
+ return { available: false, hint: error instanceof Error ? error.message : String(error) };
163
+ }
164
+ const { dirAvailable, files } = await this.listMigrationFiles();
165
+ const pending = dirAvailable ? files.filter((file) => !completed.includes(file)) : [];
166
+ return { completed, dirAvailable, lastRun: state.lastRun, pending, source: 'table' };
167
+ }
74
168
  const db = this.connection?.db;
75
169
  if (!db) {
76
170
  return { available: false, hint: 'No MongoDB connection is available.' };
@@ -6,7 +6,19 @@ import { CoreAiInteractionService } from '../../ai/services/core-ai-interaction.
6
6
  import { CoreBetterAuthUserMapper } from '../../better-auth/core-better-auth-user.mapper.js';
7
7
  import { CoreErrorCodeService } from '../../error-code/core-error-code.service.js';
8
8
  import { CorePermissionsService } from '../../permissions/core-permissions.service.js';
9
- import { HubCronData, HubErrorCodesData, HubUnavailable } from '../interfaces/hub-panels.interface.js';
9
+ import { redactUrl } from '../../../common/persistence/data-source.config.js';
10
+ import {
11
+ getPersistedModels,
12
+ getPersistenceRuntime,
13
+ getRegisteredDataStore,
14
+ } from '../../../common/persistence/persistence-runtime.registry.js';
15
+ import { ConfigService } from '../../../common/services/config.service.js';
16
+ import {
17
+ HubCronData,
18
+ HubErrorCodesData,
19
+ HubPersistenceData,
20
+ HubUnavailable,
21
+ } from '../interfaces/hub-panels.interface.js';
10
22
 
11
23
  /**
12
24
  * Single choke point for the Hub's OPTIONAL data sources.
@@ -28,6 +40,40 @@ export class CoreHubSourcesService {
28
40
  @Optional() protected readonly schedulerRegistry?: SchedulerRegistry,
29
41
  ) {}
30
42
 
43
+ /**
44
+ * Where every model registered with `CorePersistenceModule.forFeature()` is stored: its source, the database and
45
+ * engine behind it, and what that store can do. Without a SQL source everything is on the MongoDB connection.
46
+ */
47
+ getPersistence(): HubPersistenceData {
48
+ const overview = getPersistenceRuntime()?.describe() ?? {
49
+ defaultSource: 'default',
50
+ models: getPersistedModels().map((model) => ({ name: model.name, source: 'default' })),
51
+ sources: [
52
+ {
53
+ driver: 'mongodb',
54
+ host: redactUrl(ConfigService.configFastButReadOnly?.mongoose?.uri ?? ''),
55
+ name: 'default',
56
+ ownerConfigured: false,
57
+ },
58
+ ],
59
+ };
60
+ return {
61
+ ...overview,
62
+ models: overview.models
63
+ .map((model) => {
64
+ const store = getRegisteredDataStore(model.name);
65
+ const capabilities = store
66
+ ? Object.entries(store.capabilities)
67
+ .filter(([, value]) => value === true)
68
+ .map(([key]) => key)
69
+ .sort()
70
+ : [];
71
+ return { ...model, capabilities, driver: store?.driver };
72
+ })
73
+ .sort((a, b) => a.name.localeCompare(b.name)),
74
+ };
75
+ }
76
+
31
77
  /** AI availability + a light interaction/usage summary. */
32
78
  async getAi(): Promise<HubUnavailable | { available: true; totalInteractions: number }> {
33
79
  const interactionService = this.resolve<CoreAiInteractionService>(CoreAiInteractionService);
@@ -1,5 +1,5 @@
1
1
  import { Inject, Injectable, Logger, OnModuleDestroy, OnModuleInit, Optional } from '@nestjs/common';
2
- import { InjectConnection } from '@nestjs/mongoose';
2
+ import { InjectConnection } from '../../../common/persistence/mongo/mongoose-compat.js';
3
3
  import type { Connection } from 'mongoose';
4
4
 
5
5
  import { redactSensitiveText } from '../../../common/helpers/logging.helper.js';
@@ -137,6 +137,60 @@ await synchronizedMigration(migrationOptions, async (migrationSet) => {
137
137
  await synchronizedUp(migrationOptions);
138
138
  ```
139
139
 
140
+ ### SQL migrations (PostgreSQL data sources)
141
+
142
+ On a PostgreSQL source the framework migrates the schema itself at boot (new tables, columns, declared renames,
143
+ non-unique indexes, row-level security, grants). Changes that can reject or rewrite stored rows — a changed column
144
+ type, a new unique index, a rename whose old and new column both exist — are never applied automatically: the boot
145
+ stops with `SchemaMigrationRequiredError`, listing each change with a **suggested** statement.
146
+
147
+ ```bash
148
+ migrate create widen-budget --sql
149
+ ```
150
+
151
+ writes a migration whose `up` / `down` call `runSqlMigration(ownerUrl, statements)`. Paste the suggested statements,
152
+ review them, add the reverse to `down`. They run as the table owner (`NSC__DATABASE__OWNER_URL`, i.e.
153
+ `database.ownerUrl`), in one transaction, under the advisory lock the boot's schema migration takes — so a replica
154
+ booting meanwhile waits and then finds nothing left to do. In a vendor-mode project the import points at the vendored
155
+ core automatically.
156
+
157
+ `NSC__DATABASE__OWNER_URL` in the server's environment needs the URL beside it: a `database` written as a URL string
158
+ is REPLACED by the variable (the environment merge turns it into `{ ownerUrl }`), so the boot refuses that
159
+ combination. Write `database: { url: … }` in the configuration, or set `NSC__DATABASE__URL` as well.
160
+
161
+ ### Migration state on PostgreSQL (`SqlStateStore`)
162
+
163
+ A project whose default source is PostgreSQL keeps its migration state there instead of in MongoDB. Pass the OWNER's
164
+ URL to `createMigrationStore()` — it picks the store by the URL's scheme:
165
+
166
+ ```javascript
167
+ // migrations-utils/migrate.js
168
+ const { createMigrationStore } = require('@lenne.tech/nest-server');
169
+
170
+ module.exports = createMigrationStore(process.env.NSC__DATABASE__OWNER_URL);
171
+ ```
172
+
173
+ | | MongoDB (`MongoStateStore`) | PostgreSQL (`SqlStateStore`) |
174
+ | ------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
175
+ | State | one document in `migrations` | one row in `lt_migrations` (created on first use) |
176
+ | Run lock | a document in `migrations_lock`, renewed every 15 s, broken after 60 s without renewal | a transaction-scoped advisory lock held for the whole run — it ends with the connection, so a replica killed mid-run leaves nothing to break |
177
+ | Opt out of the lock | `lockCollectionName: ''` | `lockCollectionName: ''` (or `new SqlStateStore({ url, lock: false })`) |
178
+ | Connection | the MongoDB URI | the table owner (`database.ownerUrl`): migrations change the schema and every tenant's data |
179
+
180
+ The connection uses the first SQL engine the project has installed (`typeorm`, `kysely`, `drizzle`): the CLI runs
181
+ outside the application and cannot read `database.sqlEngine`. To pin one, export your own class:
182
+ `class Store extends SqlStateStore { constructor() { super({ engine: 'kysely', url: process.env.NSC__DATABASE__OWNER_URL }) } }`.
183
+
184
+ **Move the state when you switch.** A project that had MongoDB as its default source has its applied migrations in the
185
+ `migrations` collection. Pointed at the owner URL, `createMigrationStore()` starts from an empty `lt_migrations`, and the
186
+ next `migrate up` applies every migration again. Copy the state document's `lastRun` and `migrations` into the table
187
+ first (`await new SqlStateStore(ownerUrl).saveAsync(state)` with the document `MongoStateStore.loadAsync()` returns).
188
+ The Hub's Migrations panel refuses to run while the table is empty and the collection is not.
189
+
190
+ `MigrationRunner`, `synchronizedMigration()` and the `migrate` CLI accept either store. The advisory lock is held by an
191
+ open transaction for the length of the run: a server-side `idle_in_transaction_session_timeout` shorter than your
192
+ longest migration would end it early — leave that setting off (the default) for the owner role.
193
+
140
194
  ## API Reference
141
195
 
142
196
  ### MongoStateStore
@@ -17,6 +17,7 @@
17
17
  * --store, -s Path to state store module
18
18
  * --compiler, -c Compiler to use (e.g., ts:./path/to/ts-compiler.js)
19
19
  * --template-file, -t Template file for creating migrations
20
+ * --sql Create a SQL migration (statements run as the table owner, see runSqlMigration)
20
21
  * --strict Fail if a recorded migration's file is missing (default: off / tolerate).
21
22
  * Applies to up/list; down always fails hard on a missing rollback file.
22
23
  */
@@ -25,7 +26,7 @@ import * as fs from 'fs';
25
26
  import * as path from 'path';
26
27
 
27
28
  import { MigrationRunner, parseStrictEnv } from '../migration-runner.js';
28
- import { MongoStateStore } from '../mongo-state-store.js';
29
+ import type { MigrationStateStore } from '../migration-state-store.interface.js';
29
30
  import { createRequire } from 'node:module';
30
31
  import { callerDirectory } from '../../../common/helpers/module-location.helper.js';
31
32
 
@@ -42,6 +43,8 @@ interface CliOptions {
42
43
  migrationsDir: string;
43
44
  store?: string;
44
45
  strict?: boolean;
46
+ /** `create`: a SQL migration instead of the default template */
47
+ sql?: boolean;
45
48
  templateFile?: string;
46
49
  }
47
50
 
@@ -97,6 +100,40 @@ export function rewriteFrameworkSpecifier(template: string, specifier: string):
97
100
  *
98
101
  * @param coreRoot - Root of the core this CLI belongs to; defaults to the one it runs from (tests only)
99
102
  */
103
+ /**
104
+ * The template of `migrate create <name> --sql`: the statements a refused boot suggested go into `up` after review,
105
+ * their reverse into `down`. They run as the table owner (`NSC__DATABASE__OWNER_URL`, i.e. `database.ownerUrl`).
106
+ * `specifier`: the import path a vendor-mode project uses instead of the package name.
107
+ */
108
+ export function sqlMigrationTemplate(name: string, specifier?: string): string {
109
+ const template = `/**
110
+ * Migration: ${name} (SQL)
111
+ * Created: ${new Date().toISOString()}
112
+ *
113
+ * Paste the statements the boot suggested (SchemaMigrationRequiredError) and REVIEW them: a narrowed type, a new
114
+ * unique index or a rename collision can reject or rewrite stored rows. They run as the table owner, under the lock
115
+ * the boot's schema migration takes — on PostgreSQL in one transaction; on MySQL / MariaDB every DDL statement commits
116
+ * on its own, so write the migration so it can run again.
117
+ */
118
+ import { runSqlMigration } from '@lenne.tech/nest-server';
119
+
120
+ const ownerUrl = process.env.NSC__DATABASE__OWNER_URL ?? '';
121
+
122
+ export const up = async () => {
123
+ await runSqlMigration(ownerUrl, [
124
+ // PostgreSQL: 'ALTER TABLE "projects" ALTER COLUMN "budget" TYPE text COLLATE "C" USING "budget"::text',
125
+ ]);
126
+ };
127
+
128
+ export const down = async () => {
129
+ await runSqlMigration(ownerUrl, [
130
+ // the reverse of every statement in up
131
+ ]);
132
+ };
133
+ `;
134
+ return specifier ? rewriteFrameworkSpecifier(template, specifier) : template;
135
+ }
136
+
100
137
  async function createMigration(name: string, options: CliOptions, coreRoot?: string) {
101
138
  if (!name) {
102
139
  console.error('Error: Migration name is required');
@@ -116,7 +153,9 @@ async function createMigration(name: string, options: CliOptions, coreRoot?: str
116
153
  let template: string;
117
154
 
118
155
  // Use custom template if provided
119
- if (options.templateFile) {
156
+ if (options.sql) {
157
+ template = sqlMigrationTemplate(name, vendoredFrameworkSpecifier(options.migrationsDir, process.cwd(), coreRoot));
158
+ } else if (options.templateFile) {
120
159
  const templatePath = path.resolve(process.cwd(), options.templateFile);
121
160
  template = fs.readFileSync(templatePath, 'utf-8');
122
161
  const specifier = vendoredFrameworkSpecifier(options.migrationsDir, process.cwd(), coreRoot);
@@ -197,7 +236,7 @@ async function listMigrations(options: CliOptions) {
197
236
  /**
198
237
  * Load state store from module
199
238
  */
200
- function loadStateStore(storePath: string | undefined): MongoStateStore {
239
+ function loadStateStore(storePath: string | undefined): MigrationStateStore {
201
240
  if (!storePath) {
202
241
  throw new Error('--store option is required for up/down/list commands');
203
242
  }
@@ -298,6 +337,8 @@ function parseArgs(): { command: string; name?: string; options: CliOptions } {
298
337
  options.templateFile = args[++i];
299
338
  } else if (arg === '--strict') {
300
339
  options.strict = true;
340
+ } else if (arg === '--sql') {
341
+ options.sql = true;
301
342
  }
302
343
  }
303
344
 
@@ -38,4 +38,7 @@
38
38
  export * from './cli/migrate-cli.js';
39
39
  export * from './migration.helper.js';
40
40
  export * from './migration-runner.js';
41
+ export * from './migration-state-store.interface.js';
41
42
  export * from './mongo-state-store.js';
43
+ export * from './sql-migration.helper.js';
44
+ export * from './sql-state-store.js';
@@ -2,7 +2,8 @@ import * as fs from 'fs';
2
2
  import * as path from 'path';
3
3
 
4
4
  import { _endMigration, _startMigration } from './migration.helper.js';
5
- import { MongoStateStore, withMigrationLock } from './mongo-state-store.js';
5
+ import type { MigrationStateStore } from './migration-state-store.interface.js';
6
+ import { withMigrationLock } from './mongo-state-store.js';
6
7
  import { createRequire } from 'node:module';
7
8
 
8
9
  /**
@@ -98,7 +99,7 @@ export interface MigrationRunnerOptions {
98
99
  /** Pattern to match migration files (default: {@link DEFAULT_MIGRATION_FILE_PATTERN}) */
99
100
  pattern?: RegExp;
100
101
  /** State store for tracking migrations */
101
- stateStore: MongoStateStore;
102
+ stateStore: MigrationStateStore;
102
103
  /**
103
104
  * Fail hard when a migration recorded in the state has no file on disk.
104
105
  *
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Where `MigrationRunner` and the `migrate` CLI keep the applied migrations: `MongoStateStore` on MongoDB,
3
+ * `SqlStateStore` on PostgreSQL, MySQL and MariaDB. Types only.
4
+ */
5
+ export interface MigrationSet {
6
+ down?: (done?: (err?: Error) => void) => void;
7
+ lastRun?: string;
8
+ migrations: Array<{ timestamp?: number; title: string }>;
9
+ up: (done?: (err?: Error) => void) => void;
10
+ }
11
+
12
+ export interface MigrationStateStore {
13
+ /** Callback API of the `migrate` package */
14
+ load(fn: (err?: Error, set?: MigrationSet) => void): void;
15
+ loadAsync(): Promise<MigrationSet>;
16
+ /** Callback API of the `migrate` package */
17
+ save(set: MigrationSet, fn: (err?: Error) => void): void;
18
+ saveAsync(set: MigrationSet): Promise<void>;
19
+ /**
20
+ * Run `fn` while holding the store's migration lock, so concurrent runs of several replicas apply each migration
21
+ * once. A store without a lock runs `fn` unsynchronized.
22
+ */
23
+ withLock?<T>(fn: () => Promise<T>): Promise<T>;
24
+ }
@@ -1,9 +1,12 @@
1
1
  import * as fs from 'fs';
2
- import { Db, GridFSBucket, MongoClient, ObjectId } from 'mongodb';
2
+ import type { Db, MongoClient, ObjectId } from 'mongodb';
3
3
  import * as path from 'path';
4
4
 
5
5
  import { callerDirectory } from '../../common/helpers/module-location.helper.js';
6
+ import type { MigrationStateStore } from './migration-state-store.interface.js';
6
7
  import { MongoStateStore } from './mongo-state-store.js';
8
+ import { SqlStateStore } from './sql-state-store.js';
9
+ import { requireMongoPackages } from '../../common/persistence/mongo/mongo-packages.js';
7
10
 
8
11
  /**
9
12
  * Migration helper functions for database operations
@@ -60,7 +63,7 @@ export const _endMigration = async () => {
60
63
  * ```
61
64
  */
62
65
  export const getDb = async (mongoUrl: string): Promise<Db> => {
63
- const client: MongoClient = await MongoClient.connect(mongoUrl);
66
+ const client: MongoClient = await mongoDriver().MongoClient.connect(mongoUrl);
64
67
 
65
68
  // Track connection for auto-cleanup in migrations
66
69
  if (inMigrationContext) {
@@ -187,14 +190,14 @@ export const uploadFileToGridFS = async (
187
190
  ...options,
188
191
  };
189
192
 
190
- const client = await MongoClient.connect(mongoUrl);
193
+ const client = await mongoDriver().MongoClient.connect(mongoUrl);
191
194
  // Registered unconditionally — unlike `getDb()`, which only registers inside a
192
195
  // migration context. This client is always ours to close, so `_endMigration()`
193
196
  // stays a backstop for the case where the upload throws before `settle()` runs.
194
197
  activeConnections.add(client);
195
198
 
196
199
  const db = client.db();
197
- const bucket = new GridFSBucket(db, { bucketName });
200
+ const bucket = new (mongoDriver().GridFSBucket)(db, { bucketName });
198
201
  const writeStream = bucket.openUploadStream(filename);
199
202
 
200
203
  const readStream = fs.createReadStream(sourcePath);
@@ -276,10 +279,10 @@ export const uploadFileToGridFS = async (
276
279
  * the same time serializes instead of applying the same migration twice (the container
277
280
  * entrypoint runs migrations on every boot). Pass an empty string to opt out.
278
281
  *
279
- * @param mongoUrl - MongoDB connection URI
280
- * @param collectionName - Optional collection name (default: 'migrations')
282
+ * @param databaseUrl - MongoDB connection URI, or the PostgreSQL / MySQL / MariaDB URL of the table owner (`database.ownerUrl`)
283
+ * @param collectionName - Optional collection name (default: 'migrations'; on SQL the table `lt_migrations`)
281
284
  * @param lockCollectionName - Lock collection name (default: 'migrations_lock'); `''` disables locking
282
- * @returns MongoStateStore class that can be used with migrate CLI
285
+ * @returns A state store class (MongoStateStore or SqlStateStore) that can be used with the migrate CLI
283
286
  *
284
287
  * @example
285
288
  * ```typescript
@@ -288,23 +291,45 @@ export const uploadFileToGridFS = async (
288
291
  * const config = require('../src/config.env');
289
292
  *
290
293
  * module.exports = createMigrationStore(config.default.mongoose.uri);
294
+ * // A project whose default source is PostgreSQL:
295
+ * // module.exports = createMigrationStore(process.env.NSC__DATABASE__OWNER_URL);
291
296
  * ```
292
297
  */
293
298
  export const createMigrationStore = (
294
- mongoUrl: string,
299
+ databaseUrl: string,
295
300
  collectionName: string = 'migrations',
296
301
  lockCollectionName: string = 'migrations_lock',
297
302
  // Explicit return type: the returned class is anonymous to the declaration emitter, and
298
303
  // MongoStateStore has private members, so an inferred type cannot be written to the .d.ts
299
304
  // (TS4094).
300
- ): new () => MongoStateStore => {
305
+ // MongoStateStore's own fields stay in the type (optional: a SQL store has none), so code reading them keeps compiling
306
+ ): new () => MigrationStateStore & Partial<Pick<MongoStateStore, 'lockCollectionName' | 'mongodbHost'>> => {
307
+ // A SQL URL (the OWNER's, `database.ownerUrl`) keeps the state in a table and serialises runs with a database lock;
308
+ // `lockCollectionName` set to '' disables that lock there too. The names default to the framework's own
309
+ // `lt_migrations` table, a custom `collectionName` is used as the table name
310
+ if (/^(postgres(ql)?|mysql|mariadb):/i.test(databaseUrl ?? '')) {
311
+ return class SqlMigrationStateStore extends SqlStateStore {
312
+ constructor() {
313
+ super({
314
+ lock: !!lockCollectionName,
315
+ tableName: collectionName === 'migrations' ? 'lt_migrations' : collectionName,
316
+ url: databaseUrl,
317
+ });
318
+ }
319
+ };
320
+ }
301
321
  return class MigrationStateStore extends MongoStateStore {
302
322
  constructor() {
303
323
  super({
304
324
  collectionName,
305
325
  lockCollectionName: lockCollectionName || undefined,
306
- uri: mongoUrl,
326
+ uri: databaseUrl,
307
327
  });
308
328
  }
309
329
  };
310
330
  };
331
+
332
+ /** The MongoDB driver — a MongoDB migration needs it, a project without MongoDB never reaches this */
333
+ function mongoDriver() {
334
+ return requireMongoPackages('A MongoDB migration (store or helper)').mongodb;
335
+ }