@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
@@ -0,0 +1,130 @@
1
+ import { createRequire } from 'node:module';
2
+ import { join } from 'node:path';
3
+
4
+ import type * as NestMongoose from '@nestjs/mongoose';
5
+ import type * as Mongodb from 'mongodb';
6
+ import type * as Mongoose from 'mongoose';
7
+
8
+ import { callerDirectory } from '../../helpers/module-location.helper.js';
9
+
10
+ /**
11
+ * MongoDB's libraries — `mongoose`, `@nestjs/mongoose` and `mongodb` — are OPTIONAL peers since 12.1.0: a project that
12
+ * keeps its data in PostgreSQL installs none of them. Every module of the core that needs one at runtime takes it from
13
+ * here instead of importing it, because a static import of a package that is not installed fails the moment the
14
+ * barrel is loaded — long before anything could say which feature wanted it.
15
+ *
16
+ * Loaded synchronously: `@Prop()` and `@Schema()` run while a model class is DEFINED, and a project's own model file
17
+ * calls `SchemaFactory.createForClass()` right after — the decorators of the core's base classes must have reached
18
+ * Mongoose's metadata storage by then. `createRequire()` from this file's location resolves the packages the way a
19
+ * static import of the core would (the package's own peers in npm mode, the project's dependencies in vendor mode),
20
+ * and Node hands `require()` and `import` the same module instance: `mongoose` and `mongodb` are CommonJS, and
21
+ * `@nestjs/mongoose` (ESM only) is loaded through `require(esm)`, which shares the ESM loader's cache.
22
+ *
23
+ * Import-free leaf apart from the location helper — `import type` only — so it can sit below every module that needs
24
+ * it without joining an import cycle.
25
+ */
26
+
27
+ /** The three packages, when installed */
28
+ export interface MongoPackages {
29
+ /** The MongoDB driver: the project's own `mongodb`, else the one Mongoose ships (`mongoose.mongo`) */
30
+ mongodb: typeof Mongodb;
31
+ mongoose: typeof Mongoose;
32
+ nestMongoose: typeof NestMongoose;
33
+ }
34
+
35
+ /** MongoDB support was needed, and its libraries are not installed */
36
+ export class MongoPackagesMissingError extends Error {
37
+ override readonly name = 'MongoPackagesMissingError';
38
+ }
39
+
40
+ const PACKAGE_SPECIFIERS = ['mongoose', '@nestjs/mongoose'] as const;
41
+
42
+ /** Resolves like a static import of this module would */
43
+ const requireHere = createRequire(join(callerDirectory(), 'mongo-packages.js'));
44
+
45
+ /** `undefined` until the first look, `null` when the packages are not installed */
46
+ let cached: MongoPackages | null | undefined;
47
+
48
+ /**
49
+ * The packages when installed, else `undefined`. Throws when only one of `mongoose` / `@nestjs/mongoose` is installed:
50
+ * that is a broken installation, not a choice, and guessing either way would hide it.
51
+ */
52
+ export function optionalMongoPackages(): MongoPackages | undefined {
53
+ if (cached === undefined) {
54
+ cached = loadMongoPackages() ?? null;
55
+ }
56
+ return cached ?? undefined;
57
+ }
58
+
59
+ /**
60
+ * The packages, or a named error saying which feature needed them and what to install.
61
+ *
62
+ * @param feature what needs MongoDB, in the words of the configuration ("the `mongoose` configuration", "GridFS")
63
+ */
64
+ export function requireMongoPackages(feature: string): MongoPackages {
65
+ const packages = optionalMongoPackages();
66
+ if (!packages) {
67
+ throw new MongoPackagesMissingError(
68
+ `${feature} needs MongoDB, and its libraries are not installed. They are optional peer dependencies of ` +
69
+ '@lenne.tech/nest-server since 12.1.0 — add them to the project: `pnpm add mongoose @nestjs/mongoose mongodb` ' +
70
+ '(the versions in the migration guide 12.0.x → 12.1.x).',
71
+ );
72
+ }
73
+ return packages;
74
+ }
75
+
76
+ /**
77
+ * Better-Auth's MongoDB adapter — imported only where Better-Auth keeps its data in MongoDB, because it loads the
78
+ * MongoDB driver as it is evaluated
79
+ */
80
+ export function requireBetterAuthMongoAdapter(): (db: unknown) => unknown {
81
+ requireMongoPackages('Better-Auth on MongoDB (the user model is not routed to a SQL source)');
82
+ return (requireHere('better-auth/adapters/mongodb') as { mongodbAdapter: (db: unknown) => unknown }).mongodbAdapter;
83
+ }
84
+
85
+ /** Whether MongoDB's libraries are installed */
86
+ export function hasMongoPackages(): boolean {
87
+ return !!optionalMongoPackages();
88
+ }
89
+
90
+ function loadMongoPackages(): MongoPackages | undefined {
91
+ const [mongoose, nestMongoose] = PACKAGE_SPECIFIERS.map((specifier) => optionalRequire(specifier));
92
+ if (!mongoose && !nestMongoose) {
93
+ return undefined;
94
+ }
95
+ if (!mongoose || !nestMongoose) {
96
+ const missing = mongoose ? '@nestjs/mongoose' : 'mongoose';
97
+ throw new MongoPackagesMissingError(
98
+ `MongoDB support needs both mongoose and @nestjs/mongoose; ${missing} is not installed. Install it, or remove ` +
99
+ 'the other one if the project keeps no data in MongoDB.',
100
+ );
101
+ }
102
+ const mongodb = optionalRequire('mongodb') ?? (mongoose as typeof Mongoose).mongo;
103
+ return {
104
+ mongodb: mongodb as typeof Mongodb,
105
+ mongoose: mongoose as typeof Mongoose,
106
+ nestMongoose: nestMongoose as typeof NestMongoose,
107
+ };
108
+ }
109
+
110
+ /** The package, or `undefined` when it is not installed — any other loading error is a real one and propagates */
111
+ function optionalRequire(specifier: string): unknown {
112
+ try {
113
+ return requireHere(specifier);
114
+ } catch (error) {
115
+ if (isNotInstalled(error, specifier)) {
116
+ return undefined;
117
+ }
118
+ throw error;
119
+ }
120
+ }
121
+
122
+ /** A "module not found" for the package itself — not for something the package failed to load */
123
+ function isNotInstalled(error: unknown, specifier: string): boolean {
124
+ const { code, message } = (error ?? {}) as { code?: string; message?: string };
125
+ return (
126
+ (code === 'MODULE_NOT_FOUND' || code === 'ERR_MODULE_NOT_FOUND') &&
127
+ typeof message === 'string' &&
128
+ (message.includes(`'${specifier}'`) || message.includes(`"${specifier}"`))
129
+ );
130
+ }
@@ -0,0 +1,129 @@
1
+ import { Inject } from '@nestjs/common';
2
+ import type { Query } from 'mongoose';
3
+
4
+ import { HexObjectId } from './hex-object-id.js';
5
+ import {
6
+ DeclaredSchema,
7
+ declaredSchema,
8
+ markRaw,
9
+ recordModelDeclaration,
10
+ recordPropDeclaration,
11
+ } from './model-declarations.js';
12
+ import { optionalMongoPackages, requireMongoPackages } from './mongo-packages.js';
13
+
14
+ /**
15
+ * The parts of `@nestjs/mongoose` and `mongoose` the core declares its models, injections and ids with — usable
16
+ * whether or not MongoDB's libraries are installed (`mongo-packages.ts`). Since 12.1.0 the same names are exported for
17
+ * projects: a model file that imports `Prop`, `Schema` and `SchemaFactory` from `@lenne.tech/nest-server` works on
18
+ * MongoDB and on PostgreSQL alike, and installs nothing of MongoDB's where it is not used.
19
+ *
20
+ * - The decorators always RECORD what they declare (`model-declarations.ts`): that record is where a model's
21
+ * descriptor comes from when Mongoose is not there to build a schema. With Mongoose installed they also apply the
22
+ * real decorator, at the moment the original would have run — so a project's own `SchemaFactory.createForClass()`
23
+ * sees the core's fields exactly as before.
24
+ * - The injection tokens are computed here, identically to `@nestjs/mongoose` (pinned by
25
+ * `tests/unit/mongoose-compat.spec.ts`): a token is a string, and a service of the core must be constructible in a
26
+ * project that has no MongoDB at all.
27
+ */
28
+
29
+ /** `@nestjs/mongoose`'s name for the default connection */
30
+ export const DEFAULT_CONNECTION_NAME = 'DatabaseConnection';
31
+
32
+ /** The DI token of a connection — `getConnectionToken()` of `@nestjs/mongoose` */
33
+ export function getConnectionToken(name?: string): string {
34
+ return name && name !== DEFAULT_CONNECTION_NAME ? `${name}Connection` : DEFAULT_CONNECTION_NAME;
35
+ }
36
+
37
+ /** The DI token of a model — `getModelToken()` of `@nestjs/mongoose` */
38
+ export function getModelToken(model: string, connectionName?: string): string {
39
+ return connectionName === undefined ? `${model}Model` : `${getConnectionToken(connectionName)}/${model}Model`;
40
+ }
41
+
42
+ /**
43
+ * `@InjectModel()` — the model's Mongoose model where MongoDB is installed, else a stand-in that refuses data access;
44
+ * either way bound to the model's data store, which a `CrudService` follows (`CorePersistenceModule.forFeature()`)
45
+ */
46
+ export function InjectModel(model: string, connectionName?: string): ParameterDecorator & PropertyDecorator {
47
+ return Inject(getModelToken(model, connectionName));
48
+ }
49
+
50
+ /** `@InjectConnection()` — the Mongoose connection, `null` where no MongoDB is configured */
51
+ export function InjectConnection(name?: string): ParameterDecorator & PropertyDecorator {
52
+ return Inject(getConnectionToken(name));
53
+ }
54
+
55
+ /** `@Schema()` of `@nestjs/mongoose` */
56
+ export function Schema(options?: Record<string, any>): ClassDecorator {
57
+ return (target) => {
58
+ recordModelDeclaration(target, options);
59
+ optionalMongoPackages()?.nestMongoose.Schema(options as any)(target);
60
+ };
61
+ }
62
+
63
+ /** `@Prop()` of `@nestjs/mongoose` */
64
+ export function Prop(options?: Record<string, any>): PropertyDecorator {
65
+ return (target, propertyKey) => {
66
+ recordPropDeclaration(target, propertyKey, options);
67
+ optionalMongoPackages()?.nestMongoose.Prop(options as any)(target, propertyKey);
68
+ };
69
+ }
70
+
71
+ /** `raw()` of `@nestjs/mongoose` — an inline object definition, kept as written where Mongoose is not installed */
72
+ export function raw(definition: Record<string, any>): Record<string, any> {
73
+ const packages = optionalMongoPackages();
74
+ return packages ? packages.nestMongoose.raw(definition) : markRaw(definition);
75
+ }
76
+
77
+ /**
78
+ * `SchemaFactory.createForClass()` of `@nestjs/mongoose` — the Mongoose schema, or the recorded declaration
79
+ * (`DeclaredSchema`) where Mongoose is not installed
80
+ */
81
+ export const SchemaFactory = {
82
+ createForClass(target: abstract new (...args: any[]) => any): any {
83
+ const packages = optionalMongoPackages();
84
+ return packages ? packages.nestMongoose.SchemaFactory.createForClass(target as any) : declaredSchema(target);
85
+ },
86
+ };
87
+
88
+ /**
89
+ * `new Schema(definition, options)` of `mongoose` — for a model declared inline rather than through a class. A field
90
+ * whose shape is free-form is declared `{ type: Object }`, which Mongoose stores as `Mixed`.
91
+ */
92
+ export function createSchema(definition: Record<string, any>, options: Record<string, any> = {}): any {
93
+ const packages = optionalMongoPackages();
94
+ return packages
95
+ ? new packages.mongoose.Schema(definition, options)
96
+ : new DeclaredSchema({ definition: { ...definition }, options: { ...options } });
97
+ }
98
+
99
+ /**
100
+ * The type to declare an ObjectId field with (`@Prop({ type: ObjectIdType, ref })`): Mongoose's `Schema.Types.ObjectId`
101
+ * where installed, else the class the descriptor recognises as an id
102
+ */
103
+ export function objectIdType(): unknown {
104
+ return optionalMongoPackages()?.mongoose.Schema.Types.ObjectId ?? HexObjectId;
105
+ }
106
+
107
+ /** A new ObjectId, or one for the given hex string / ObjectId — `new Types.ObjectId(value)` */
108
+ export function newObjectId(value?: { toHexString(): string } | string): any {
109
+ const packages = optionalMongoPackages();
110
+ return packages ? new packages.mongoose.Types.ObjectId(value as any) : new HexObjectId(value);
111
+ }
112
+
113
+ /** `Types.ObjectId.isValid()` — accepts what an ObjectId can be built from */
114
+ export function isValidObjectId(value: unknown): boolean {
115
+ const packages = optionalMongoPackages();
116
+ return packages ? packages.mongoose.Types.ObjectId.isValid(value as any) : HexObjectId.isValid(value);
117
+ }
118
+
119
+ /** Whether a value is a Mongoose query (`instanceof Query`) — never where Mongoose is not installed */
120
+ export function isMongooseQuery(value: unknown): value is Query<any, any> {
121
+ const Query = optionalMongoPackages()?.mongoose.Query;
122
+ return !!Query && value instanceof Query;
123
+ }
124
+
125
+ /** A GridFS bucket on a MongoDB database — GridFS IS MongoDB, so its absence is a configuration error, named as such */
126
+ export function createGridFsBucket(db: unknown, options?: { bucketName?: string }): any {
127
+ const { mongodb } = requireMongoPackages('GridFS (file.storage: gridfs)');
128
+ return new mongodb.GridFSBucket(db as any, options);
129
+ }
@@ -0,0 +1,18 @@
1
+ import { Global, Module } from '@nestjs/common';
2
+
3
+ import { getConnectionToken } from './mongoose-compat.js';
4
+
5
+ /**
6
+ * The Mongoose connection token where no MongoDB is configured (`database` names no MongoDB source): `null`.
7
+ *
8
+ * Services of the core receive the connection through `@InjectConnection()` and use it only on their MongoDB path —
9
+ * on a SQL source they work through the data store. Without this provider every one of them would fail DI in a project
10
+ * that keeps its data in PostgreSQL alone; with it, a MongoDB path that is reached anyway fails with a named error
11
+ * (`CorePersistenceModule` stand-ins, `requireMongoPackages()`) instead of a missing-provider stack trace at boot.
12
+ */
13
+ @Global()
14
+ @Module({
15
+ exports: [getConnectionToken()],
16
+ providers: [{ provide: getConnectionToken(), useValue: null }],
17
+ })
18
+ export class NoMongoConnectionModule {}
@@ -0,0 +1,121 @@
1
+ import type { Collection } from 'mongodb';
2
+
3
+ import type { LockStore } from './lock-store.interface.js';
4
+
5
+ /** The duplicate-key error code, decided by code rather than by matching message text. */
6
+ const DUPLICATE_KEY = 11000;
7
+
8
+ export interface MongoLockStoreOptions {
9
+ /**
10
+ * Field holding the lease key — `_id` by default. Any other field gets a unique index before the first claim: the
11
+ * claim's atomicity rests on it, exactly as it rests on `_id` otherwise.
12
+ */
13
+ keyField?: string;
14
+ /**
15
+ * A lock format older versions wrote: a timestamp and no `expiresAt`. Such a lock counts as expired once the
16
+ * timestamp is older than `staleAfterMs` — the rule those versions apply themselves — and every lock this store
17
+ * writes or renews carries the timestamp too, so an older replica applies its rule to it in a rolling deploy. Both
18
+ * sides then decide on one document, and a lease is never held twice.
19
+ */
20
+ legacyTimestamp?: { field: string; staleAfterMs: number };
21
+ }
22
+
23
+ /**
24
+ * Leases in a MongoDB collection: one document per key (`_id` by default), with `owner` and `expiresAt`.
25
+ *
26
+ * Works on the native collection on purpose — a lease collection has no Mongoose schema and no tenant,
27
+ * audit or password semantics a plugin could add. A TTL index on `expiresAt` may be added for garbage
28
+ * collection; correctness never depends on it, because every claim compares `expiresAt` itself.
29
+ */
30
+ export class MongoLockStore implements LockStore {
31
+ protected readonly keyField: string;
32
+ private keyIndex?: Promise<unknown>;
33
+
34
+ constructor(
35
+ protected readonly collection: Collection<any>,
36
+ protected readonly options: MongoLockStoreOptions = {},
37
+ ) {
38
+ this.keyField = options.keyField ?? '_id';
39
+ }
40
+
41
+ async release(key: string, owner: string): Promise<boolean> {
42
+ const result = await this.collection.deleteOne({ [this.keyField]: key, owner });
43
+ return result.deletedCount === 1;
44
+ }
45
+
46
+ async renew(key: string, owner: string, ttlSeconds: number): Promise<boolean> {
47
+ const now = new Date();
48
+ const result = await this.collection.updateOne(
49
+ { [this.keyField]: key, expiresAt: { $gt: now }, owner },
50
+ { $set: { ...this.legacyStamp(now), expiresAt: new Date(now.getTime() + ttlSeconds * 1000) } },
51
+ );
52
+ return result.matchedCount === 1;
53
+ }
54
+
55
+ async tryAcquire(key: string, owner: string, ttlSeconds: number): Promise<boolean> {
56
+ await this.ensureKeyIndex();
57
+ const now = new Date();
58
+ const legacy = this.options.legacyTimestamp;
59
+ // Matches only an EXPIRED lease, which is taken over in one atomic step. A held lease does not
60
+ // match, so the upsert tries to insert the same key and fails with a duplicate key: lost. A missing
61
+ // lease is inserted: won. Two contenders for one expired lease cannot both match — the first update
62
+ // moves expiresAt into the future before the second is evaluated.
63
+ const expired = legacy
64
+ ? {
65
+ $or: [
66
+ { expiresAt: { $lte: now } },
67
+ {
68
+ expiresAt: { $exists: false },
69
+ [legacy.field]: { $lt: new Date(now.getTime() - legacy.staleAfterMs) },
70
+ },
71
+ ],
72
+ }
73
+ : { expiresAt: { $lte: now } };
74
+ try {
75
+ await this.collection.updateOne(
76
+ { [this.keyField]: key, ...expired },
77
+ {
78
+ $set: {
79
+ ...(this.keyField === '_id' ? {} : { [this.keyField]: key }),
80
+ ...this.legacyStamp(now),
81
+ acquiredAt: now,
82
+ expiresAt: new Date(now.getTime() + ttlSeconds * 1000),
83
+ owner,
84
+ },
85
+ },
86
+ { upsert: true },
87
+ );
88
+ return true;
89
+ } catch (error) {
90
+ if ((error as { code?: number })?.code !== DUPLICATE_KEY) {
91
+ throw error;
92
+ }
93
+ if (legacy) {
94
+ // A lock of a version that wrote no timestamp at all: start its clock now — as those versions did — rather
95
+ // than obeying it forever or breaking it at once (its holder may well be alive)
96
+ await this.collection.updateOne(
97
+ { [this.keyField]: key, expiresAt: { $exists: false }, [legacy.field]: { $exists: false } },
98
+ { $set: { [legacy.field]: now } },
99
+ );
100
+ }
101
+ return false;
102
+ }
103
+ }
104
+
105
+ /** The timestamp older versions read, refreshed with every claim and renewal */
106
+ private legacyStamp(now: Date): Record<string, Date> {
107
+ return this.options.legacyTimestamp ? { [this.options.legacyTimestamp.field]: now } : {};
108
+ }
109
+
110
+ private async ensureKeyIndex(): Promise<void> {
111
+ if (this.keyField === '_id') {
112
+ return;
113
+ }
114
+ this.keyIndex ??= this.collection.createIndex({ [this.keyField]: 1 }, { unique: true }).catch((error) => {
115
+ // Retried on the next claim: without the index a second contender could insert a second lock
116
+ this.keyIndex = undefined;
117
+ throw error;
118
+ });
119
+ await this.keyIndex;
120
+ }
121
+ }
@@ -0,0 +1,232 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import type { Model } from 'mongoose';
3
+
4
+ import { getStringIds } from '../helpers/id.helper.js';
5
+ import {
6
+ assertAccessReason,
7
+ assertArrayField,
8
+ assertProjection,
9
+ assertSampleSize,
10
+ assertSelectFields,
11
+ } from './store-guards.js';
12
+ import type {
13
+ DataStore,
14
+ DataStoreUpdate,
15
+ FindOptions,
16
+ PushOptions,
17
+ StoreCapabilities,
18
+ StoredRecord,
19
+ UpdateOptions,
20
+ Where,
21
+ } from './data-store.interface.js';
22
+
23
+ /** What MongoDB offers through Mongoose. Transactions need a replica set and are not assumed. */
24
+ export const MONGOOSE_STORE_CAPABILITIES: Readonly<StoreCapabilities> = Object.freeze({
25
+ aggregatePipeline: true,
26
+ changeFeed: false,
27
+ gridfs: true,
28
+ idType: 'objectId',
29
+ mongoosePopulate: true,
30
+ rawFilterArm: true,
31
+ rls: false,
32
+ textSearch: true,
33
+ transactions: false,
34
+ });
35
+
36
+ /**
37
+ * The MongoDB data store: the neutral port over a Mongoose model.
38
+ *
39
+ * Every operation runs through a Model method, never the native collection, so the security plugins
40
+ * (tenant isolation before and after, audit fields, role guard, system roles, password hashing) fire
41
+ * exactly as for any other Mongoose call. Filters and updates pass through untouched — they already
42
+ * are the Mongo-operator form — except that the neutral `id` is addressed as `_id`.
43
+ */
44
+ export class MongooseDataStore<T = Record<string, any>> implements DataStore<T> {
45
+ readonly capabilities = MONGOOSE_STORE_CAPABILITIES;
46
+ readonly driver = 'mongodb';
47
+ protected readonly logger = new Logger(MongooseDataStore.name);
48
+
49
+ constructor(protected readonly model: Model<any>) {}
50
+
51
+ get modelName(): string {
52
+ return this.model.modelName;
53
+ }
54
+
55
+ async count(where?: Where<T>): Promise<number> {
56
+ return this.model.countDocuments(toMongoFilter(where)).exec();
57
+ }
58
+
59
+ async sum(field: string, where?: Where<T>): Promise<{ count: number; sum: number }> {
60
+ assertSelectFields([field]);
61
+ // An aggregation's $match is not cast like a query: cast it through a query of the model first
62
+ const match = this.model.find().cast(this.model, toMongoFilter(where));
63
+ const [row] = await this.model
64
+ .aggregate<{ count: number; sum: number }>([
65
+ { $match: match },
66
+ { $group: { _id: null, count: { $sum: 1 }, sum: { $sum: { $ifNull: [`$${field}`, 0] } } } },
67
+ ])
68
+ .exec();
69
+ return { count: row?.count ?? 0, sum: row?.sum ?? 0 };
70
+ }
71
+
72
+ async deleteById(id: string): Promise<null | StoredRecord<T>> {
73
+ return toRecord<T>(await this.model.findByIdAndDelete(id).lean().exec());
74
+ }
75
+
76
+ async deleteMany(where: Where<T>): Promise<number> {
77
+ const result = await this.model.deleteMany(toMongoFilter(where)).exec();
78
+ return result.deletedCount;
79
+ }
80
+
81
+ async deleteOne(where: Where<T>): Promise<null | StoredRecord<T>> {
82
+ return toRecord<T>(await this.model.findOneAndDelete(toMongoFilter(where)).lean().exec());
83
+ }
84
+
85
+ async distinct(field: string, where?: Where<T>): Promise<unknown[]> {
86
+ return this.model.distinct(field, toMongoFilter(where)).exec();
87
+ }
88
+
89
+ async find(where?: Where<T>, options: FindOptions = {}): Promise<StoredRecord<T>[]> {
90
+ const sample = options.sample === undefined ? undefined : assertSampleSize(options.sample);
91
+ let query = this.model.find(toMongoFilter(where));
92
+ if (options.select || options.exclude) query = query.select(toProjection(options));
93
+ if (options.sort) query = query.sort(options.sort);
94
+ if (options.skip !== undefined) query = query.skip(options.skip);
95
+ if (options.limit !== undefined) query = query.limit(options.limit);
96
+ if (options.collation) query = query.collation(options.collation as any);
97
+ const docs = await query.lean().exec();
98
+ const records = (docs as unknown[]).map((doc) => toRecord<T>(doc));
99
+ // Drawn from the page this query returned, like `$sample` after `$limit`. CrudService.findAndCount() on MongoDB
100
+ // keeps its own aggregation; this path serves callers of the port.
101
+ return sample === undefined ? records : randomSample(records, sample);
102
+ }
103
+
104
+ async findById(id: string, options: Pick<FindOptions, 'exclude' | 'select'> = {}): Promise<null | StoredRecord<T>> {
105
+ let query = this.model.findById(id);
106
+ if (options.select || options.exclude) query = query.select(toProjection(options));
107
+ return toRecord<T>(await query.lean().exec());
108
+ }
109
+
110
+ async findOne(where: Where<T>, options: Omit<FindOptions, 'limit' | 'skip'> = {}): Promise<null | StoredRecord<T>> {
111
+ let query = this.model.findOne(toMongoFilter(where));
112
+ if (options.select || options.exclude) query = query.select(toProjection(options));
113
+ if (options.sort) query = query.sort(options.sort);
114
+ if (options.collation) query = query.collation(options.collation as any);
115
+ return toRecord<T>(await query.lean().exec());
116
+ }
117
+
118
+ async insert(record: Partial<T>): Promise<StoredRecord<T>> {
119
+ // `create()` runs the save hooks, so tenant stamping, audit fields and password hashing apply
120
+ const created = await this.model.create(record);
121
+ return toRecord<T>(created.toObject());
122
+ }
123
+
124
+ native<N = unknown>(reason: string): N {
125
+ assertAccessReason(reason, 'native');
126
+ this.logger.debug(`Native model access: ${reason} (Model: ${this.modelName})`);
127
+ return this.model as unknown as N;
128
+ }
129
+
130
+ async pullFromArray(id: string, field: string, condition: unknown): Promise<void> {
131
+ assertArrayField(field, 'pullFromArray');
132
+ await this.model
133
+ .findByIdAndUpdate(id, { $pull: { [field]: condition } } as any)
134
+ .lean()
135
+ .exec();
136
+ }
137
+
138
+ async pushToArray(id: string, field: string, items: readonly unknown[], options: PushOptions = {}): Promise<void> {
139
+ assertArrayField(field, 'pushToArray');
140
+ if (!items.length) {
141
+ return;
142
+ }
143
+ const push: Record<string, unknown> = { $each: [...items] };
144
+ if (options.slice !== undefined) push.$slice = options.slice;
145
+ if (options.position !== undefined) push.$position = options.position;
146
+ if (options.sort) push.$sort = options.sort;
147
+ await this.model
148
+ .findByIdAndUpdate(id, { $push: { [field]: push } } as any)
149
+ .lean()
150
+ .exec();
151
+ }
152
+
153
+ raw<N = unknown>(reason: string): N {
154
+ assertAccessReason(reason, 'raw');
155
+ this.logger.warn(`[SECURITY] Native collection access: ${reason} (Model: ${this.modelName})`);
156
+ return this.model.collection as unknown as N;
157
+ }
158
+
159
+ async updateById(
160
+ id: string,
161
+ update: DataStoreUpdate<T>,
162
+ options: UpdateOptions = {},
163
+ ): Promise<null | StoredRecord<T>> {
164
+ const updated = await this.model
165
+ .findByIdAndUpdate(id, update as any, {
166
+ returnDocument: 'after',
167
+ ...(options.timestamps === false ? { timestamps: false } : {}),
168
+ })
169
+ .lean()
170
+ .exec();
171
+ return toRecord<T>(updated);
172
+ }
173
+
174
+ async updateMany(where: Where<T>, update: DataStoreUpdate<T>): Promise<number> {
175
+ const result = await this.model.updateMany(toMongoFilter(where), update as any).exec();
176
+ return result.matchedCount;
177
+ }
178
+
179
+ async updateOne(where: Where<T>, update: DataStoreUpdate<T>): Promise<null | StoredRecord<T>> {
180
+ const updated = await this.model
181
+ .findOneAndUpdate(toMongoFilter(where), update as any, { returnDocument: 'after' })
182
+ .lean()
183
+ .exec();
184
+ return toRecord<T>(updated);
185
+ }
186
+ }
187
+
188
+ /** The neutral `id` is `_id` in MongoDB — at the top level and inside `$and` / `$or` / `$nor`. */
189
+ export function toMongoFilter(where: undefined | Where<any>): Record<string, any> {
190
+ if (!where) {
191
+ return {};
192
+ }
193
+ const filter: Record<string, any> = {};
194
+ for (const [key, value] of Object.entries(where)) {
195
+ if (key === 'id') {
196
+ filter._id = value;
197
+ } else if ((key === '$and' || key === '$or' || key === '$nor') && Array.isArray(value)) {
198
+ filter[key] = value.map((entry) => toMongoFilter(entry));
199
+ } else {
200
+ filter[key] = value;
201
+ }
202
+ }
203
+ return filter;
204
+ }
205
+
206
+ /** A lean document as a neutral record: the id as a string under `id`, no `_id`, no version key. */
207
+ function toRecord<T>(doc: unknown): StoredRecord<T> {
208
+ if (!doc) {
209
+ return null;
210
+ }
211
+ const { __v: _version, _id, ...fields } = doc as Record<string, any>;
212
+ return { ...fields, id: _id === undefined ? fields.id : getStringIds(_id) } as StoredRecord<T>;
213
+ }
214
+
215
+ function toProjection(options: Pick<FindOptions, 'exclude' | 'select'>): string {
216
+ assertProjection(options);
217
+ if (options.exclude?.length) {
218
+ return options.exclude.map((field) => `-${field}`).join(' ');
219
+ }
220
+ return (options.select ?? []).map((field) => (field === 'id' ? '_id' : field)).join(' ');
221
+ }
222
+
223
+ /** `size` items of `items` in random order (a partial Fisher–Yates shuffle) */
224
+ function randomSample<I>(items: I[], size: number): I[] {
225
+ const pool = [...items];
226
+ const count = Math.min(size, pool.length);
227
+ for (let index = 0; index < count; index++) {
228
+ const pick = index + Math.floor(Math.random() * (pool.length - index));
229
+ [pool[index], pool[pick]] = [pool[pick], pool[index]];
230
+ }
231
+ return pool.slice(0, count);
232
+ }