@futdevpro/nts-dynamo 1.15.102 → 1.15.104

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 (371) hide show
  1. package/.c8rc.json +26 -26
  2. package/.copilot/patterns.json +7 -7
  3. package/.cursor/rules/__assistant_guide.mdc +30 -30
  4. package/.cursor/rules/_ag_backend-structure.mdc +85 -85
  5. package/.cursor/rules/_ag_backend.mdc +16 -16
  6. package/.cursor/rules/_ag_frontend-structure.mdc +86 -86
  7. package/.cursor/rules/_ag_frontend.mdc +39 -39
  8. package/.cursor/rules/_ag_import-rules.mdc +44 -44
  9. package/.cursor/rules/_ag_naming.mdc +115 -115
  10. package/.cursor/rules/_ag_should-be.mdc +6 -6
  11. package/.cursor/rules/ai_development_guide.md +60 -60
  12. package/.cursor/rules/cursor-rules.md +160 -160
  13. package/.cursor/rules/default-command.mdc +464 -464
  14. package/.cursor/rules/error_code_pattern.md +39 -39
  15. package/.cursor/rules/saved rule mcp server use.md +15 -15
  16. package/.dynamo/pipeline.cicd.config.json +3 -3
  17. package/.vscode/settings.json +10 -10
  18. package/HOWTO.md +15 -15
  19. package/LICENSE +21 -21
  20. package/__documentations/nts-integration-tests-2026-03-17.md +26 -26
  21. package/__documentations/plans/BEDROCK-HYPERPLAN.md +95 -95
  22. package/_specifications/BACKLOG.md +92 -92
  23. package/_specifications/TODO.md +15 -15
  24. package/_specifications/agent.md +138 -138
  25. package/build/_collections/client-safe-error.util.d.ts +9 -3
  26. package/build/_collections/client-safe-error.util.d.ts.map +1 -1
  27. package/build/_collections/client-safe-error.util.js +32 -3
  28. package/build/_collections/client-safe-error.util.js.map +1 -1
  29. package/eslint.config.js +3 -3
  30. package/nodemon.json +24 -24
  31. package/package.json +3 -3
  32. package/pnpm-workspace.yaml +5 -5
  33. package/scripts/run-coverage-tests.js +28 -28
  34. package/spec/support/helpers/spec-reporter-loader.js +359 -359
  35. package/spec/support/helpers/ts-node-helper.js +93 -93
  36. package/spec/support/jasmine.coverage.json +24 -24
  37. package/spec/support/jasmine.json +24 -24
  38. package/src/_collections/archive.util.spec.ts +57 -57
  39. package/src/_collections/archive.util.ts +18 -18
  40. package/src/_collections/atlas-default-db-options.const.ts +9 -9
  41. package/src/_collections/client-safe-error.util.spec.ts +58 -2
  42. package/src/_collections/client-safe-error.util.ts +38 -3
  43. package/src/_collections/default-fallback-cache-max-age.const.spec.ts +11 -11
  44. package/src/_collections/default-fallback-cache-max-age.const.ts +2 -2
  45. package/src/_collections/default-not-found-page.const.spec.ts +19 -19
  46. package/src/_collections/default-not-found-page.const.ts +22 -22
  47. package/src/_collections/default-socket-path.const.spec.ts +12 -12
  48. package/src/_collections/default-socket-path.const.ts +2 -2
  49. package/src/_collections/get-environment-settings.util.spec.ts +210 -210
  50. package/src/_collections/get-environment-settings.util.ts +48 -48
  51. package/src/_collections/global-settings.const.ts +126 -126
  52. package/src/_collections/sample.env +21 -21
  53. package/src/_collections/star.controller.spec.ts +224 -224
  54. package/src/_collections/star.controller.ts +129 -129
  55. package/src/_enums/data-model-type.enum.ts +14 -14
  56. package/src/_enums/data-service-function.enum.ts +24 -24
  57. package/src/_enums/predefined-data-types.enum.ts +16 -16
  58. package/src/_enums/route-security.enum.ts +12 -12
  59. package/src/_models/control-models/api-call-params.control-model.spec.ts +152 -152
  60. package/src/_models/control-models/api-call-params.control-model.ts +142 -142
  61. package/src/_models/control-models/app-ext-system-controls.control-model.spec.ts +52 -52
  62. package/src/_models/control-models/app-ext-system-controls.control-model.ts +9 -9
  63. package/src/_models/control-models/app-params.control-model.spec.ts +225 -225
  64. package/src/_models/control-models/app-params.control-model.ts +136 -136
  65. package/src/_models/control-models/app-system-controls.control-model.spec.ts +31 -31
  66. package/src/_models/control-models/app-system-controls.control-model.ts +9 -9
  67. package/src/_models/control-models/endpoint-params.control-model.spec.ts +669 -669
  68. package/src/_models/control-models/endpoint-params.control-model.ts +628 -628
  69. package/src/_models/control-models/http-settings.control-model.spec.ts +77 -77
  70. package/src/_models/control-models/http-settings.control-model.ts +37 -37
  71. package/src/_models/control-models/system-control.control-model.spec.ts +27 -27
  72. package/src/_models/control-models/system-control.control-model.ts +12 -12
  73. package/src/_models/interfaces/certification-settings.interface.ts +7 -7
  74. package/src/_models/interfaces/environment-settings.interface.ts +59 -59
  75. package/src/_models/interfaces/global-log-settings.interface.ts +171 -171
  76. package/src/_models/interfaces/global-service-settings.interface.ts +47 -47
  77. package/src/_models/interfaces/global-settings.interface.ts +286 -286
  78. package/src/_models/interfaces/routing-module-settings.interface.ts +21 -21
  79. package/src/_models/interfaces/static-client-settings.interface.spec.ts +29 -29
  80. package/src/_models/interfaces/static-client-settings.interface.ts +36 -36
  81. package/src/_models/types/db-update.type.ts +100 -100
  82. package/src/_modules/ai/_models/ai-input-interfaces.ts +117 -117
  83. package/src/_modules/ai/_models/ai-test-generation-result.interface.ts +16 -16
  84. package/src/_modules/ai/_modules/anthropic/_services/aai-user-key.control-service.ts +138 -138
  85. package/src/_modules/ai/_modules/anthropic/index.ts +5 -5
  86. package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.spec.ts +242 -242
  87. package/src/_modules/ai/_modules/document-ai/_collections/dai-chunking.util.ts +639 -639
  88. package/src/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.spec.ts +295 -295
  89. package/src/_modules/ai/_modules/document-ai/_collections/dai-code-chunking.util.ts +518 -518
  90. package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.spec.ts +209 -209
  91. package/src/_modules/ai/_modules/document-ai/_collections/dai-document.util.ts +85 -85
  92. package/src/_modules/ai/_modules/document-ai/_enums/dai-compare-result-type.enum.ts +7 -7
  93. package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-doc-chunk.data-model.ts +146 -146
  94. package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-doc-page.data-model.ts +162 -162
  95. package/src/_modules/ai/_modules/document-ai/_models/data-models/dai-document.data-model.ts +99 -99
  96. package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-code-chunk.interface.ts +68 -68
  97. package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-doc-chunk-compare-result.interface.ts +18 -18
  98. package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-doc-page-compare-result.interface.ts +19 -19
  99. package/src/_modules/ai/_modules/document-ai/_models/interfaces/dai-document-compare-result.interface.ts +25 -25
  100. package/src/_modules/ai/_modules/document-ai/index.ts +30 -30
  101. package/src/_modules/ai/_modules/fdp-ai/_services/fdpai-user-key.control-service.ts +189 -189
  102. package/src/_modules/ai/_modules/fdp-ai/index.ts +5 -5
  103. package/src/_modules/ai/_modules/open-ai/_collections/oai-global-settings.const.ts +9 -9
  104. package/src/_modules/ai/_modules/open-ai/_collections/oai-llm-predefined-requests-hu.conts.ts +82 -82
  105. package/src/_modules/ai/_modules/open-ai/_collections/oai-llm-predefined-requests.conts.ts +75 -75
  106. package/src/_modules/ai/_modules/open-ai/_enums/oai-gpt-message-role.enum.ts +45 -45
  107. package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-global-settings.interface.ts +7 -7
  108. package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-gpt-message.interface.ts +7 -7
  109. package/src/_modules/ai/_modules/open-ai/_models/interfaces/oai-llm-predefined-requests.interface.ts +57 -57
  110. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-doc-chunk-data.service.ts +292 -292
  111. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-document.data-service.spec.ts +342 -342
  112. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.spec.ts +550 -550
  113. package/src/_modules/ai/_modules/open-ai/_services/data-services/oai-vector-data.service.ts +630 -630
  114. package/src/_modules/ai/_modules/open-ai/_services/oai-embedding.control-service.spec.ts +332 -332
  115. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.spec.ts +462 -462
  116. package/src/_modules/ai/_modules/open-ai/_services/oai-llm-chat.service-base.ts +634 -634
  117. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.spec.ts +489 -489
  118. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.tools.spec.ts +173 -173
  119. package/src/_modules/ai/_modules/open-ai/_services/oai-llm.service-base.ts +1033 -1033
  120. package/src/_modules/ai/_modules/open-ai/_services/oai-user-key.control-service.ts +157 -157
  121. package/src/_modules/ai/_services/ai-embedding-mock.service.spec.ts +115 -115
  122. package/src/_modules/ai/_services/ai-embedding-mock.service.ts +212 -212
  123. package/src/_modules/ai/_services/ai-embedding-provider.registry.spec.ts +110 -110
  124. package/src/_modules/ai/_services/ai-embedding-provider.registry.ts +110 -110
  125. package/src/_modules/ai/_services/ai-embedding.service-base.spec.ts +98 -98
  126. package/src/_modules/ai/_services/ai-embedding.service-base.ts +48 -48
  127. package/src/_modules/ai/_services/ai-llm-chat.service-base.spec.ts +229 -229
  128. package/src/_modules/ai/_services/ai-llm-chat.service-base.ts +68 -68
  129. package/src/_modules/ai/_services/ai-llm.service-base.spec.ts +250 -250
  130. package/src/_modules/ai/_services/ai-llm.service-base.ts +519 -519
  131. package/src/_modules/ai/_services/ai-provider.service-base.spec.ts +158 -158
  132. package/src/_modules/ai/_services/ai-user-key.service-base.ts +59 -59
  133. package/src/_modules/ai/_services/lmstudio-embedding.control-service.spec.ts +197 -197
  134. package/src/_modules/ai/_services/lmstudio-embedding.control-service.ts +371 -371
  135. package/src/_modules/ai/index.ts +23 -23
  136. package/src/_modules/assistant/_collections/ass-global-settings.const.ts +13 -13
  137. package/src/_modules/assistant/_collections/ass.util.spec.ts +176 -176
  138. package/src/_modules/assistant/_collections/ass.util.ts +50 -50
  139. package/src/_modules/assistant/_models/ass-global-settings.interface.ts +15 -15
  140. package/src/_modules/assistant/_services/ass-io.control-service.spec.ts +140 -140
  141. package/src/_modules/assistant/_services/ass-main.control-service.spec.ts +192 -192
  142. package/src/_modules/assistant/_services/ass-main.control-service.ts +107 -107
  143. package/src/_modules/bot/_collections/bot-default-commands.const.ts +12 -12
  144. package/src/_modules/bot/_collections/bot-global-settings.const.ts +39 -39
  145. package/src/_modules/bot/_models/bot-channel-wrapper.interface.ts +62 -62
  146. package/src/_modules/bot/_models/bot-command.interface.ts +8 -8
  147. package/src/_modules/bot/_models/bot-global-settings.interface.ts +96 -96
  148. package/src/_modules/bot/_models/bot-last-mention-date.interface.ts +6 -6
  149. package/src/_modules/bot/_models/bot-last-message-date.interface.ts +5 -5
  150. package/src/_modules/bot/_models/bot-user-wrapper.interface.ts +41 -41
  151. package/src/_modules/bot/_modules/discord-bot/_models/dib-platform.types.ts +9 -9
  152. package/src/_modules/bot/_modules/discord-bot/_services/dib-messaging-provider.control-service.spec.ts +431 -431
  153. package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.spec.ts +160 -160
  154. package/src/_modules/bot/_modules/dynamo-bot/_collections/dyb-operations.util.ts +55 -55
  155. package/src/_modules/bot/_modules/dynamo-bot/_models/dyb-platform.types.ts +15 -15
  156. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.spec.ts +374 -374
  157. package/src/_modules/bot/_modules/dynamo-bot/_services/dyb-messaging-provider.control-service.ts +447 -447
  158. package/src/_modules/bot/_modules/dynamo-bot/index.ts +15 -15
  159. package/src/_modules/bot/_modules/slack-bot/_models/slb-platform.types.ts +9 -9
  160. package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.spec.ts +344 -344
  161. package/src/_modules/bot/_modules/slack-bot/_services/slb-messaging-provider.control-service.ts +197 -197
  162. package/src/_modules/bot/_modules/teams-bot/_models/teb-platform.types.ts +9 -9
  163. package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.spec.ts +345 -345
  164. package/src/_modules/bot/_modules/teams-bot/_services/teb-messaging-provider.control-service.ts +197 -197
  165. package/src/_modules/bot/_services/bot-commands.control-service.spec.ts +116 -116
  166. package/src/_modules/bot/_services/bot-io.control-service.spec.ts +285 -285
  167. package/src/_modules/bot/_services/bot-main.control-service.spec.ts +208 -208
  168. package/src/_modules/bot/_services/bot-messaging-provider.service-base.spec.ts +349 -349
  169. package/src/_modules/bot/_services/bot-routines.control-service.spec.ts +111 -111
  170. package/src/_modules/custom-data/custom-data.controller.spec.ts +49 -49
  171. package/src/_modules/custom-data/custom-data.controller.ts +67 -67
  172. package/src/_modules/custom-data/custom-data.data-service.spec.ts +54 -54
  173. package/src/_modules/custom-data/custom-data.data-service.ts +21 -21
  174. package/src/_modules/custom-data/get-custom-data-routing-module.util.spec.ts +28 -28
  175. package/src/_modules/custom-data/get-custom-data-routing-module.util.ts +24 -24
  176. package/src/_modules/custom-data/index.ts +9 -9
  177. package/src/_modules/data-readers/_collections/dynts-sqlite-reader.util.spec.ts +161 -161
  178. package/src/_modules/data-readers/_collections/dynts-sqlite-reader.util.ts +203 -203
  179. package/src/_modules/data-readers/_models/interfaces/dynts-sqlite-reader.interface.ts +33 -33
  180. package/src/_modules/data-readers/index.ts +11 -11
  181. package/src/_modules/defaults/_collections/default-endpoints.util.ts +487 -487
  182. package/src/_modules/defaults/_models/default-user.data-model.ts +72 -72
  183. package/src/_modules/defaults/_services/default-auth.service.spec.ts +269 -269
  184. package/src/_modules/defaults/_services/default-auth.service.ts +177 -177
  185. package/src/_modules/defaults/_services/default-socket-events.service.spec.ts +42 -42
  186. package/src/_modules/defaults/_services/default-socket-events.service.ts +61 -61
  187. package/src/_modules/defaults/_services/default-user.data-service.spec.ts +187 -187
  188. package/src/_modules/defaults/_services/default-user.data-service.ts +98 -98
  189. package/src/_modules/defaults/index.ts +17 -17
  190. package/src/_modules/discord-assistant/_collections/dias-global-settings.const.ts +19 -19
  191. package/src/_modules/discord-assistant/_collections/dias.util.spec.ts +366 -366
  192. package/src/_modules/discord-assistant/_collections/dias.util.ts +132 -132
  193. package/src/_modules/discord-assistant/_models/dias-global-settings.interface.ts +19 -19
  194. package/src/_modules/discord-assistant/_models/dias-knowledge.data-model.ts +52 -52
  195. package/src/_modules/discord-assistant/_services/dias-chunk.data-service.ts +177 -177
  196. package/src/_modules/discord-assistant/_services/dias-io.control-service.spec.ts +108 -108
  197. package/src/_modules/discord-assistant/_services/dias-io.control-service.ts +69 -69
  198. package/src/_modules/discord-assistant/_services/dias-main.control-service.spec.ts +22 -22
  199. package/src/_modules/discord-assistant/_services/dias-main.control-service.ts +27 -27
  200. package/src/_modules/discord-assistant/_services/dias.service-base.spec.ts +195 -195
  201. package/src/_modules/discord-assistant/_services/dias.service-base.ts +76 -76
  202. package/src/_modules/discord-assistant/index.ts +38 -38
  203. package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.spec.ts +34 -34
  204. package/src/_modules/discord-assistant-voiced/_services/dias-discord-bot.control-service.ts +11 -11
  205. package/src/_modules/discord-assistant-voiced/index.ts +36 -36
  206. package/src/_modules/discord-bot/_collections/dibo-default-commands.const.ts +16 -16
  207. package/src/_modules/discord-bot/_collections/dibo-global-settings.conts.ts +55 -55
  208. package/src/_modules/discord-bot/_collections/dibo-operations.util.spec.ts +214 -214
  209. package/src/_modules/discord-bot/_collections/dibo-operations.util.ts +387 -387
  210. package/src/_modules/discord-bot/_models/dibo-command.interface.ts +12 -12
  211. package/src/_modules/discord-bot/_models/dibo-global-settings.interface.ts +98 -98
  212. package/src/_modules/discord-bot/_models/dibo-last-mention-date.inteface.ts +7 -7
  213. package/src/_modules/discord-bot/_models/dibo-last-message-date.interface.ts +6 -6
  214. package/src/_modules/discord-bot/_services/dibo-commands.control-service.spec.ts +154 -154
  215. package/src/_modules/discord-bot/_services/dibo-commands.control-service.ts +153 -153
  216. package/src/_modules/discord-bot/_services/dibo-io.control-service.spec.ts +264 -264
  217. package/src/_modules/discord-bot/_services/dibo-io.control-service.ts +306 -306
  218. package/src/_modules/discord-bot/_services/dibo-main.control-service.spec.ts +408 -408
  219. package/src/_modules/discord-bot/_services/dibo-main.control-service.ts +487 -487
  220. package/src/_modules/discord-bot/_services/dibo-routines.control-service.spec.ts +105 -105
  221. package/src/_modules/discord-bot/index.ts +36 -36
  222. package/src/_modules/local-vector-search/_enums/lvs-search-mode.enum.ts +35 -35
  223. package/src/_modules/local-vector-search/_models/data-models/lvs-vector-persist.data-model.ts +59 -59
  224. package/src/_modules/local-vector-search/_models/lvs-search-result.interface.ts +17 -17
  225. package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.spec.ts +418 -418
  226. package/src/_modules/local-vector-search/_services/lvs-doc-chunk-data.service.ts +276 -276
  227. package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.spec.ts +480 -480
  228. package/src/_modules/local-vector-search/_services/lvs-local-vector-search.data-service.ts +416 -416
  229. package/src/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.spec.ts +198 -198
  230. package/src/_modules/local-vector-search/_services/lvs-persistent-vector-pool.control-service.ts +146 -146
  231. package/src/_modules/local-vector-search/_services/lvs-vector-persist.data-service.spec.ts +167 -167
  232. package/src/_modules/local-vector-search/_services/lvs-vector-persist.data-service.ts +106 -106
  233. package/src/_modules/local-vector-search/_services/lvs-vector-pool.control-service.spec.ts +507 -507
  234. package/src/_modules/local-vector-search/_services/lvs-vector-pool.control-service.ts +272 -272
  235. package/src/_modules/local-vector-search/index.ts +16 -16
  236. package/src/_modules/logs/index.ts +11 -11
  237. package/src/_modules/mcp/_models/interfaces/dynts-mcp.interface.ts +111 -111
  238. package/src/_modules/mcp/_services/dynts-mcp-server.service-base.spec.ts +142 -142
  239. package/src/_modules/mcp/_services/dynts-mcp-server.service-base.ts +120 -120
  240. package/src/_modules/mcp/_services/dynts-mcp.adapter.ts +168 -168
  241. package/src/_modules/mcp/index.ts +13 -13
  242. package/src/_modules/messaging/README.md +354 -354
  243. package/src/_modules/messaging/_collections/get-messaging-routing-module.util.ts +26 -26
  244. package/src/_modules/messaging/_collections/msg-global-settings.const.ts +22 -22
  245. package/src/_modules/messaging/_collections/msg.util.spec.ts +226 -226
  246. package/src/_modules/messaging/_models/msg-global-settings.interface.ts +37 -37
  247. package/src/_modules/messaging/_services/msg-conversation.data-service.ts +146 -146
  248. package/src/_modules/messaging/_services/msg-events.service.spec.ts +219 -219
  249. package/src/_modules/messaging/_services/msg-events.service.ts +267 -267
  250. package/src/_modules/messaging/_services/msg-integration.control-service.ts +179 -179
  251. package/src/_modules/messaging/_services/msg-main.control-service.spec.ts +147 -147
  252. package/src/_modules/messaging/_services/msg-main.control-service.ts +571 -571
  253. package/src/_modules/messaging/_services/msg-message.data-service.ts +129 -129
  254. package/src/_modules/messaging/_services/msg.controller.spec.ts +201 -201
  255. package/src/_modules/messaging/index.ts +30 -30
  256. package/src/_modules/mock/app-extended-server.mock.ts +201 -201
  257. package/src/_modules/mock/app-integration-test.mock.ts +51 -51
  258. package/src/_modules/mock/app-params.mock.spec.ts +21 -21
  259. package/src/_modules/mock/app-params.mock.ts +9 -9
  260. package/src/_modules/mock/app-server.mock.ts +188 -188
  261. package/src/_modules/mock/auth-service.mock.spec.ts +47 -47
  262. package/src/_modules/mock/auth-service.mock.ts +28 -28
  263. package/src/_modules/mock/controller.mock.spec.ts +26 -26
  264. package/src/_modules/mock/controller.mock.ts +16 -16
  265. package/src/_modules/mock/data-model.mock.spec.ts +111 -111
  266. package/src/_modules/mock/data-model.mock.ts +82 -82
  267. package/src/_modules/mock/email-service-collection.mock.spec.ts +24 -24
  268. package/src/_modules/mock/email-service-collection.mock.ts +15 -15
  269. package/src/_modules/mock/email-service.mock.spec.ts +17 -17
  270. package/src/_modules/mock/email-service.mock.ts +20 -20
  271. package/src/_modules/mock/email-template.mock.html +14 -14
  272. package/src/_modules/mock/endpoint.mock.ts +91 -91
  273. package/src/_modules/mock/socket-client.mock.spec.ts +40 -40
  274. package/src/_modules/mock/socket-client.mock.ts +45 -45
  275. package/src/_modules/mock/socket-server.mock.spec.ts +44 -44
  276. package/src/_modules/mock/socket-server.mock.ts +46 -46
  277. package/src/_modules/oauth2/_routes/oauth2.controller.spec.ts +107 -107
  278. package/src/_modules/oauth2/_routes/oauth2.controller.ts +98 -98
  279. package/src/_modules/oauth2/_services/oauth2.auth-service.spec.ts +254 -254
  280. package/src/_modules/oauth2/_services/oauth2.auth-service.ts +232 -232
  281. package/src/_modules/oauth2/_services/oauth2.control-service.spec.ts +585 -585
  282. package/src/_modules/oauth2/_services/oauth2.control-service.ts +653 -653
  283. package/src/_modules/oauth2/index.ts +17 -17
  284. package/src/_modules/scheduler/_models/scheduler-job.interface.ts +35 -35
  285. package/src/_modules/scheduler/get-scheduler-routing-module.util.ts +33 -33
  286. package/src/_modules/scheduler/index.ts +8 -8
  287. package/src/_modules/scheduler/scheduler.controller.spec.ts +42 -42
  288. package/src/_modules/scheduler/scheduler.controller.ts +69 -69
  289. package/src/_modules/scheduler/scheduler.service.spec.ts +141 -141
  290. package/src/_modules/scheduler/scheduler.service.ts +176 -176
  291. package/src/_modules/scoped-config/_enums/dynts-scoped-config-level.enum.ts +22 -22
  292. package/src/_modules/scoped-config/_models/data-models/dynts-scoped-config.data-model.ts +81 -81
  293. package/src/_modules/scoped-config/_models/interfaces/dynts-scoped-config.interface.ts +107 -107
  294. package/src/_modules/scoped-config/_services/dynts-scoped-config.control-service.spec.ts +306 -306
  295. package/src/_modules/scoped-config/_services/dynts-scoped-config.control-service.ts +295 -295
  296. package/src/_modules/scoped-config/_services/dynts-scoped-config.data-service.spec.ts +118 -118
  297. package/src/_modules/scoped-config/_services/dynts-scoped-config.data-service.ts +105 -105
  298. package/src/_modules/scoped-config/index.ts +17 -17
  299. package/src/_modules/server/errors/errors.control-service.spec.ts +238 -238
  300. package/src/_modules/server/errors/errors.control-service.ts +100 -100
  301. package/src/_modules/server/errors/errors.controller.spec.ts +268 -268
  302. package/src/_modules/server/errors/errors.controller.ts +515 -515
  303. package/src/_modules/server/errors/errors.data-service.spec.ts +480 -480
  304. package/src/_modules/server/index.ts +30 -30
  305. package/src/_modules/server/server-status/server-status-snapshot.control-service.spec.ts +70 -70
  306. package/src/_modules/server/server-status/server-status-snapshot.control-service.ts +17 -17
  307. package/src/_modules/server/server-status/server-status-snapshot.data-service.spec.ts +77 -77
  308. package/src/_modules/server/server-status/server-status-snapshot.data-service.ts +37 -37
  309. package/src/_modules/server/server-status/server-status.control-service.spec.ts +576 -576
  310. package/src/_modules/server/server-status/server-status.control-service.ts +396 -396
  311. package/src/_modules/server/server-status/server-status.controller.spec.ts +255 -255
  312. package/src/_modules/server/server-status/server-status.controller.ts +292 -292
  313. package/src/_modules/socket/_enums/socket-security.enum.ts +11 -11
  314. package/src/_modules/socket/_models/socket-client-service-params.control-model.spec.ts +32 -32
  315. package/src/_modules/socket/_models/socket-client-service-params.control-model.ts +22 -22
  316. package/src/_modules/socket/_models/socket-presence.control-model.spec.ts +164 -164
  317. package/src/_modules/socket/_models/socket-presence.control-model.ts +210 -210
  318. package/src/_modules/socket/_models/socket-server-service-params.control-model.spec.ts +46 -46
  319. package/src/_modules/socket/_models/socket-server-service-params.control-model.ts +22 -22
  320. package/src/_modules/socket/_services/socket-client.service.spec.ts +15 -15
  321. package/src/_modules/socket/_services/socket-client.service.ts +260 -260
  322. package/src/_modules/socket/_services/socket-server.service.spec.ts +11 -11
  323. package/src/_modules/socket/app-extended.integration.spec.ts +85 -85
  324. package/src/_modules/socket/app-extended.server.ts +642 -642
  325. package/src/_modules/socket/index.ts +42 -42
  326. package/src/_modules/test/get-test-routing-module.util.spec.ts +28 -28
  327. package/src/_modules/test/get-test-routing-module.util.ts +23 -23
  328. package/src/_modules/test/index.ts +11 -11
  329. package/src/_modules/test/test.controller.spec.ts +72 -72
  330. package/src/_modules/test/test.controller.ts +115 -115
  331. package/src/_modules/usage/get-usage-routing-module.util.ts +22 -22
  332. package/src/_modules/usage/index.ts +15 -15
  333. package/src/_modules/usage/usage.controller.spec.ts +81 -81
  334. package/src/_modules/usage/usage.controller.ts +126 -126
  335. package/src/_modules/usage/usage.data-service.spec.ts +332 -332
  336. package/src/_modules/usage/usage.data-service.ts +185 -185
  337. package/src/_services/base/api.service-base.spec.ts +125 -125
  338. package/src/_services/base/api.service-base.ts +74 -74
  339. package/src/_services/base/archive-data.service.spec.ts +209 -209
  340. package/src/_services/base/archive-data.service.ts +223 -223
  341. package/src/_services/base/data.service.spec.ts +729 -729
  342. package/src/_services/base/data.service.ts +2758 -2758
  343. package/src/_services/base/db.service.spec.ts +160 -160
  344. package/src/_services/base/db.service.ts +1644 -1644
  345. package/src/_services/base/singleton.service-base.spec.ts +28 -28
  346. package/src/_services/base/singleton.service-base.ts +24 -24
  347. package/src/_services/base/singleton.service.spec.ts +114 -114
  348. package/src/_services/base/singleton.service.ts +38 -38
  349. package/src/_services/core/api.service.spec.ts +140 -140
  350. package/src/_services/core/auth.service.spec.ts +159 -159
  351. package/src/_services/core/auth.service.ts +174 -174
  352. package/src/_services/core/email.service.spec.ts +85 -85
  353. package/src/_services/core/email.service.ts +757 -757
  354. package/src/_services/core/global.service.spec.ts +292 -292
  355. package/src/_services/core/global.service.ts +487 -487
  356. package/src/_services/core/memory-guard.service.spec.ts +245 -245
  357. package/src/_services/core/memory-guard.service.ts +481 -481
  358. package/src/_services/core/service-collection.service.spec.ts +46 -46
  359. package/src/_services/core/service-collection.service.ts +6 -6
  360. package/src/_services/route/controller.service.spec.ts +53 -53
  361. package/src/_services/route/controller.service.ts +148 -148
  362. package/src/_services/route/routing-module.service.spec.ts +98 -98
  363. package/src/_services/route/routing-module.service.ts +330 -330
  364. package/src/_services/server/app.server.ts +1985 -1985
  365. package/src/_services/shared.static-service.spec.ts +99 -99
  366. package/src/_services/shared.static-service.ts +78 -78
  367. package/src/index.ts +100 -100
  368. package/tsconfig.app.json +12 -12
  369. package/tsconfig.json +42 -42
  370. package/.dynamo/logs/cicd-pipeline/output.log +0 -2855
  371. package/.dynamo/logs/cicd-pipeline/status.json +0 -74
@@ -1,1644 +1,1644 @@
1
-
2
- import * as mongoose from 'mongoose';
3
- import { Schema } from 'mongoose';
4
-
5
- import {
6
- DyFM_AnyError,
7
- DyFM_BasicProperty_Type,
8
- DyFM_DataModel_Params,
9
- DyFM_DataProperties,
10
- DyFM_DataProperty_Params,
11
- DyFM_DBFilter, DyFM_DBFilterSimple, DyFM_DBSort,
12
- DyFM_Error,
13
- DyFM_Error_Settings, DyFM_ErrorLevel,
14
- DyFM_Log,
15
- DyFM_Metadata,
16
- DyFM_Object
17
- } from '@futdevpro/fsm-dynamo';
18
- import { DyNTS_archiveSuffix } from '../../_collections/archive.util';
19
- import { DyNTS_DBUpdate } from '../../_models/types/db-update.type';
20
- import { DyNTS_DBQueryOptions } from '../../_models/interfaces/db-query-options.interface';
21
- import { DyNTS_global_settings } from '../../_collections/global-settings.const';
22
-
23
- /**
24
- * DB Service for MongoDB
25
- */
26
- export class DyNTS_DBService<T extends DyFM_Metadata> {
27
-
28
- serviceName: string;
29
-
30
- dataModel/* : mongoose.Model<T> */; // = mongoose.model(this.dataParams.dataName, this.getSchema());
31
-
32
- /* private depDataName: string; */
33
- private readonly depKeys: string[] = [];
34
-
35
- defaultErrorUserMsg =
36
- `We encountered an unhandled DB Error, ` +
37
- `\nplease contact the responsible development team.`;
38
-
39
- /**
40
- * @param dataName name the model
41
- * @param typeSample sample data for scheme creation (dont include DyFM_Metadata!)
42
- * @param schemaSettings additional settings for specific parameters as unique, required, minlength or maxlength
43
- * schemaSettings also MUST contain specific types that differs from the listed above (Array, Date)
44
- */
45
- constructor(
46
- public dataParams: DyFM_DataModel_Params<T>
47
- ){
48
- try {
49
- this.serviceName = this.constructor?.name;
50
-
51
- if (!this.dataParams.dataName || typeof this.dataParams.dataName !== 'string') {
52
- throw new Error(
53
- `dbName not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
54
- );
55
- }
56
-
57
- if (!this.dataParams.constructed?.()) {
58
- throw new DyFM_Error({
59
- error: new Error(
60
- `DataModelParams is not constructed properly! (${this.dataParams.dataName}) ` +
61
- `Use the DyFM_DataModel_Params.constructor to construct it properly! (NTS DB)`
62
- ),
63
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-C01`,
64
- additionalContent: { dataParams: this.dataParams },
65
- __localStack: this.dataParams.stackLocation,
66
- });
67
- }
68
-
69
- try {
70
- this.dataModel = mongoose.model(this.dataParams.dataName, this.getSchema());
71
- } catch (error) {
72
- if (mongoose.models[this.dataParams.dataName]) {
73
- this.dataModel = mongoose.models[this.dataParams.dataName];
74
- } else {
75
- throw error;
76
- }
77
- }
78
-
79
- this.lookForDependencyDataSettings();
80
- } catch (error) {
81
- throw new DyFM_Error({
82
- message:
83
- `DyNTS_DBService construction failed! "${dataParams.dataName}" - "${this.serviceName}"`,
84
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-C00`,
85
- level: DyFM_ErrorLevel.critical,
86
- additionalContent: { dataParams: this.dataParams },
87
- error,
88
- });
89
- }
90
- }
91
-
92
- /**
93
- * save new data
94
- * @param data data
95
- * @returns data
96
- */
97
- async createData(data: T, issuer: string): Promise<T> {
98
- data.__created = new Date();
99
- data.__lastModified = new Date();
100
- data.__createdBy = issuer;
101
- data.__lastModifiedBy = issuer;
102
-
103
- const dataModel = new this.dataModel(data);
104
- const newData: T = await dataModel.save().then((res): T => {
105
- if (res) {
106
- return res?.toObject() as T;
107
-
108
- } else {
109
- throw new DyFM_Error({
110
- ...this._getDefaultErrorSettings(
111
- 'createData',
112
- new Error(
113
- `createData failed, save "${this.dataParams.dataName}" result not found! (NTS DB)`
114
- ),
115
- issuer
116
- ),
117
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CD1`,
118
- additionalContent: { data },
119
- issuer,
120
- });
121
- }
122
- }).catch((error): void => {
123
- if (error?.flag?.includes('DYNAMO')) {
124
- throw error;
125
-
126
- } else {
127
- throw new DyFM_Error({
128
- ...this._getDefaultErrorSettings('createData', error, issuer),
129
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CD0`,
130
- additionalContent: {
131
- data: data,
132
- dataModel: this.dataModel,
133
- },
134
- message:
135
- `createData failed, Create new "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
136
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
137
- issuer,
138
- });
139
- }
140
- });
141
-
142
- return this.stringifyDataId(newData, 'createData');
143
- }
144
-
145
- /**
146
- * Find data by _id and update
147
- * @param data data
148
- * @returns data
149
- */
150
- async modifyData(data: T, issuer: string, dontUpdateModified?: boolean): Promise<T> {
151
- if (this.dataParams.forbidModify) {
152
- await this.modifyThrowMethod(data, issuer);
153
- }
154
-
155
- if (!dontUpdateModified) {
156
- data.__lastModified = new Date();
157
- data.__lastModifiedBy = issuer;
158
- }
159
-
160
- /**
161
- * EZ A SZAR TELJESEN SZAR, nem friss, nem a db-be mentett adatokat ad vissza,
162
- * átír random value-kat össze vissza, WTF
163
- * */
164
- /* let newData: T = */
165
- await this.dataModel.findByIdAndUpdate(data._id, data)/* .then((res) => {
166
- if (res) {
167
- //return res?.toObject() as T;
168
- } else {
169
- throw new DyFM_Error({
170
- ...this._getDefaultErrorSettings(
171
- 'modifyData',
172
- new Error(`modifyData failed, modify "${this.dataParams.dataName}" result not found! (NTS DB)`),
173
- issuer,
174
- ),
175
-
176
- status: 204,
177
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FU1`,
178
- additionalContent: { data },
179
- issuer,
180
- });
181
- }
182
- }) */.catch((error): void => {
183
- throw new DyFM_Error({
184
- ...this._getDefaultErrorSettings('modifyData', error, issuer),
185
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FU0`,
186
- additionalContent: { data },
187
- message:
188
- `modifyData "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
189
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
190
- issuer,
191
- });
192
- });
193
-
194
- return this.stringifyDataId(data, 'modifyData');
195
- }
196
-
197
- // TODO: Missing issuer
198
- /**
199
- * returns data by _id,
200
- * @param id id
201
- * @returns data
202
- */
203
- async getDataById(id: string): Promise<T> {
204
- if (!id) {
205
- throw new DyFM_Error({
206
- ...this._getDefaultErrorSettings('getDataById', new Error(`No ID provided! (NTS DB)`)),
207
-
208
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GI1`,
209
- message: `get "${this.dataParams.dataName}" by ID was unsuccessful (NTS DB)`,
210
- });
211
- }
212
-
213
- const data: T = await this.dataModel
214
- .findById(id)
215
- .then((res): T => res?.toObject() as T ?? null)
216
- .catch((error): void => {
217
- throw new DyFM_Error({
218
- ...this._getDefaultErrorSettings('getDataById', error),
219
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GI0`,
220
- additionalContent: { id },
221
- message:
222
- `get "${this.dataParams.dataName}" by ID was unsuccessful (NTS DB)` +
223
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
224
- });
225
- });
226
-
227
- return this.stringifyDataId(data, 'getDataById');
228
- }
229
-
230
- // TODO: Missing issuer
231
- /**
232
- * get data by dependency data id,
233
- * !!!: throws error if not found (errorCode on not found: NTS-DBS-GD2)
234
- *
235
- * @param dependencyIdsFilter id
236
- * @returns data
237
- */
238
- async getDataByDependencyId(dependencyIdsFilter: { [key: string]: string }): Promise<T> {
239
- if (!this.depKeys.length) {
240
- throw new DyFM_Error({
241
- ...this._getDefaultErrorSettings(
242
- 'getDataByDependencyId',
243
- new Error(
244
- `dependencyDataIdKey not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
245
- )
246
- ),
247
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GD0`,
248
- });
249
- }
250
-
251
- const data: T = await this.dataModel
252
- .findOne(dependencyIdsFilter)
253
- .then((res): T => res?.toObject() as T ?? null)
254
- .catch((error): void => {
255
- throw new DyFM_Error({
256
- ...this._getDefaultErrorSettings('getDataByDependencyId', error),
257
-
258
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GD1`,
259
- additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
260
- message:
261
- `get "${this.dataParams.dataName}" by ` +
262
- `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
263
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
264
- });
265
- });
266
-
267
- return this.stringifyDataId(data, 'getDataByDependencyId');
268
- }
269
-
270
- // TODO: Missing issuer
271
- async getDataListByIds(ids: string[], findDeleted?: boolean): Promise<T[]> {
272
- const dataList: T[] = await this.dataModel
273
- .find({ _id: { $in: ids } })
274
- .then((res): T[] => res as T[] ?? [])
275
- .catch((error): void => {
276
- throw new DyFM_Error({
277
- ...this._getDefaultErrorSettings('getDataListByIds', error),
278
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GDL0`,
279
- additionalContent: { ids },
280
- message:
281
- `get "${this.dataParams.dataName}" by IDs was unsuccessful (NTS DB)` +
282
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
283
- });
284
- });
285
-
286
- if (!findDeleted) {
287
- return dataList.filter(
288
- (data: T): boolean => !data._deleted
289
- ).map(
290
- (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
291
- );
292
- } else {
293
- return dataList.map(
294
- (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
295
- );
296
- }
297
- }
298
-
299
- // TODO: Missing issuer
300
- /**
301
- * get data by dependency data id,
302
- * !!!: throws error if not found (errorCode on not found: NTS-DBS-GLD2)
303
- *
304
- * @param dependencyIdsFilter id
305
- * @returns dataList
306
- */
307
- async getDataListByDependencyId(dependencyIdsFilter: { [key: string]: string }, findDeleted?: boolean): Promise<T[]> {
308
- if (!this.depKeys.length) {
309
- throw new DyFM_Error({
310
- ...this._getDefaultErrorSettings(
311
- 'getDataListByDependencyId',
312
- new Error(
313
- `isDependencyHook not setted up for this dataModel (${this.dataParams.dataName}) (NTS DB)`
314
- )
315
- ),
316
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLD0`,
317
- additionalContent: {
318
- dataModel: this.dataModel,
319
- },
320
- });
321
- }
322
-
323
- const dataList: T[] = await this.dataModel
324
- .find(dependencyIdsFilter)
325
- .then((res): T[] => res as T[] ?? [])
326
- .catch((error): void => {
327
- throw new DyFM_Error({
328
- ...this._getDefaultErrorSettings('getDataListByDependencyId', error),
329
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLD1`,
330
- additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
331
- message:
332
- `get "${this.dataParams.dataName}" by ` +
333
- `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
334
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
335
- });
336
- });
337
-
338
- if (!findDeleted) {
339
- return dataList.filter(
340
- (data: T): boolean => !data._deleted
341
- ).map(
342
- (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
343
- );
344
- } else {
345
- return dataList.map(
346
- (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
347
- );
348
- }
349
- }
350
-
351
- // TODO: Missing issuer
352
- /**
353
- * get multiple data objects by a list of DependencyIDs,
354
- * !!!: throws error if not found (errorCode on not found: NTS-DBS-GLDS2)
355
- *
356
- * @param ids ids
357
- * @returns dataList
358
- */
359
- async getDataListByDependencyIds(dependencyKey: string, dependencyIds: string[], findDeleted?: boolean): Promise<T[]> {
360
- if (!this.depKeys.length) {
361
- throw new DyFM_Error({
362
- ...this._getDefaultErrorSettings(
363
- 'getDataListByDependencyIds',
364
- new Error(
365
- `getDataListByDependencyIds not setted up for this db-service ` +
366
- `(${this.dataParams.dataName}) (NTS DB)`
367
- )
368
- ),
369
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLDS0`,
370
- });
371
- }
372
-
373
- if (!dependencyIds?.length) {
374
- return [];
375
- }
376
-
377
- if (!dependencyKey) {
378
- throw new DyFM_Error({
379
- ...this._getDefaultErrorSettings(
380
- 'getDataListByDependencyIds',
381
- new Error(`dependencyKey is missing! (${this.dataParams.dataName}) (NTS DB)`),
382
- ),
383
- });
384
- }
385
-
386
- if (!this.depKeys.includes(dependencyKey)) {
387
- throw new DyFM_Error({
388
- ...this._getDefaultErrorSettings(
389
- 'getDataListByDependencyIds',
390
- new Error(`dependencyKey is not valid! (${dependencyKey}) (NTS DB)`),
391
- ),
392
- });
393
- }
394
-
395
- const dataList: T[] = await this.dataModel
396
- .find({
397
- [dependencyKey]: { $in: dependencyIds },
398
- })
399
- .then((res): T[] => res as T[] ?? [])
400
- .catch((error): void => {
401
- throw new DyFM_Error({
402
- ...this._getDefaultErrorSettings('getDataListByDependencyIds', error),
403
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLDS1`,
404
- additionalContent: { dependencyIds },
405
- message:
406
- `get "${this.dataParams.dataName}" by "${dependencyKey}" was unsuccessful (NTS DB)` +
407
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
408
- });
409
- });
410
-
411
- if (!findDeleted) {
412
- return dataList.filter(
413
- (data: T): boolean => !data._deleted
414
- ).map(
415
- (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyIds')
416
- );
417
- } else {
418
- return dataList.map(
419
- (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyIds')
420
- );
421
- }
422
- }
423
-
424
- // TODO: Missing issuer
425
- /**
426
- * returns all data from database,
427
- * !!!: throws error if not found (errorCode on not found: NTS-DBS-GA1)
428
- *
429
- * @returns dataList
430
- */
431
- async getAll(findDeleted?: boolean): Promise<T[]> {
432
- const dataList: T[] = await this.dataModel
433
- .find()
434
- .then((res): T[] => res as T[] ?? [])
435
- .catch((error): void => {
436
- throw new DyFM_Error({
437
- ...this._getDefaultErrorSettings('getAll', error),
438
-
439
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GA0`,
440
- message:
441
- `get all "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
442
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
443
- });
444
- });
445
-
446
- if (!findDeleted) {
447
- return dataList.filter(
448
- (data: T): boolean => !data._deleted
449
- ).map(
450
- (data: T): T => this.stringifyDataId(data, 'getAll')
451
- );
452
- } else {
453
- return dataList.map(
454
- (data: T): T => this.stringifyDataId(data, 'getAll')
455
- );
456
- }
457
- }
458
-
459
- async markDeletedById(id: string, issuer: string): Promise<void> {
460
- if (this.dataParams.forbidDelete) {
461
- await this.deleteThrowMethod(id, issuer);
462
- }
463
-
464
- await this.dataModel.findByIdAndUpdate(
465
- id,
466
- {
467
- _deleted: new Date(),
468
- _deletedBy: issuer,
469
- },
470
- /* issuer */
471
- ).catch(
472
- (error): void => {
473
- throw new DyFM_Error({
474
- ...this._getDefaultErrorSettings('markDeletedById', error, issuer),
475
-
476
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-MD0`,
477
- additionalContent: { id },
478
- message:
479
- `mark deleted "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
480
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
481
- issuer,
482
- });
483
- }
484
- );
485
- }
486
-
487
- async markDeletedByDependencyId(dependencyIdsFilter: { [key: string]: string }, issuer: string): Promise<void> {
488
- if (this.dataParams.forbidDelete) {
489
- await this.deleteThrowMethod(dependencyIdsFilter, issuer);
490
- }
491
-
492
- await this.dataModel.updateMany(
493
- dependencyIdsFilter,
494
- {
495
- _deleted: new Date(),
496
- _deletedBy: issuer,
497
- }
498
- ).catch((error): void => {
499
- throw new DyFM_Error({
500
- ...this._getDefaultErrorSettings('markDeletedByDependencyId', error, issuer),
501
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-MDD0`,
502
- additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
503
- message:
504
- `markDeleted "${this.dataParams.dataName}" by ` +
505
- `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
506
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
507
- issuer,
508
- });
509
- });
510
- }
511
-
512
- async restoreDeletedById(id: string, issuer: string): Promise<void> {
513
- await this.dataModel.findByIdAndUpdate(
514
- id,
515
- {
516
- _deleted: null,
517
- __lastModified: new Date(),
518
- __lastModifiedBy: issuer,
519
- },
520
- /* issuer */
521
- ).catch((error): void => {
522
- throw new DyFM_Error({
523
- ...this._getDefaultErrorSettings('restoreDeletedById', error, issuer),
524
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-RD0`,
525
- additionalContent: { id },
526
- message:
527
- `restoreDeleted "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
528
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
529
- issuer,
530
- });
531
- });
532
- }
533
-
534
- async restoreDeletedByDependencyId(
535
- dependencyIdsFilter: { [key: string]: string },
536
- issuer: string
537
- ): Promise<void> {
538
- await this.dataModel.updateMany(
539
- dependencyIdsFilter,
540
- {
541
- _deleted: null,
542
- __lastModified: new Date(),
543
- __lastModifiedBy: issuer,
544
- }
545
- ).catch((error): void => {
546
- throw new DyFM_Error({
547
- ...this._getDefaultErrorSettings('restoreDeletedByDependencyId', error, issuer),
548
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-RDD0`,
549
- additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
550
- message:
551
- `restoreDeleted "${this.dataParams.dataName}" by ` +
552
- `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
553
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
554
- issuer,
555
- });
556
- });
557
- }
558
-
559
- // TODO: Missing issuer
560
- async getDeletedDataList(): Promise<T[]> {
561
- const dataList: T[] = await this.dataModel
562
- .getAll()
563
- .then((res): T[] => res as T[] ?? [])
564
- .catch((error): void => {
565
- throw new DyFM_Error({
566
- ...this._getDefaultErrorSettings('getDeletedData', error),
567
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GDD0`,
568
- message:
569
- `get deleted "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
570
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
571
- });
572
- });
573
-
574
- return dataList.filter(
575
- (data: T): boolean => Boolean(data._deleted)
576
- ).map((data: T): T => this.stringifyDataId(data, 'getDeletedData'));
577
- }
578
-
579
- // TODO: Missing issuer
580
- /**
581
- * deleted data by id
582
- * @param id id
583
- */
584
- async trueDeleteDataById(id: string): Promise<void> {
585
- if (this.dataParams.forbidDelete) {
586
- await this.deleteThrowMethod(id/* , issuer */);
587
- }
588
-
589
- await this.dataModel
590
- .findByIdAndDelete(id)
591
- .catch((error): void => {
592
- throw new DyFM_Error({
593
- ...this._getDefaultErrorSettings('deleteDataById', error),
594
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DD0`,
595
- additionalContent: { id },
596
- message:
597
- `delete "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
598
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
599
- });
600
- });
601
- }
602
- readonly deleteDataById = this.trueDeleteDataById;
603
-
604
- // TODO: Missing issuer
605
- /**
606
- * deleted data by id
607
- * @param dependencyId id
608
- */
609
- async trueDeleteDataByDependencyId(dependencyIdsFilter: { [key: string]: string }): Promise<void> {
610
- if (this.dataParams.forbidDelete) {
611
- await this.deleteThrowMethod(dependencyIdsFilter/* , issuer */);
612
- }
613
-
614
- if (!this.depKeys.length) {
615
- throw new DyFM_Error({
616
- ...this._getDefaultErrorSettings(
617
- 'deleteDataByDependencyId',
618
- new Error(
619
- `dependencyDataIdKey not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
620
- )
621
- ),
622
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DDD0`,
623
- });
624
- }
625
-
626
- await this.dataModel
627
- .deleteMany(dependencyIdsFilter)
628
- .catch((error): void => {
629
- throw new DyFM_Error({
630
- ...this._getDefaultErrorSettings('deleteDataByDependencyId', error),
631
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DDD1`,
632
- additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
633
- message:
634
- `delete "${this.dataParams.dataName}" by ` +
635
- `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
636
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
637
- });
638
- });
639
- }
640
- readonly deleteDataByDependencyId = this.trueDeleteDataByDependencyId;
641
-
642
- // TODO: Missing issuer
643
- async trueDeleteAllData(): Promise<void> {
644
- if (this.dataParams.forbidDelete) {
645
- await this.deleteThrowMethod(null/* , issuer */);
646
- }
647
-
648
- await this.dataModel.deleteMany().catch((error): void => {
649
- throw new DyFM_Error({
650
- ...this._getDefaultErrorSettings('deleteAllData', error),
651
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DAD0`,
652
- message:
653
- `delete all "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
654
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
655
- });
656
- });
657
- }
658
- readonly deleteAllData = this.trueDeleteAllData;
659
-
660
- // TODO: Missing issuer
661
- /**
662
- * returns search result for searchBy object params
663
- * can use lists or xRange values for searchBy obj properties
664
- *
665
- * @param filterBy filter
666
- * @param narrowByDependencyIds id
667
- * @returns dataList
668
- */
669
- async searchData(
670
- filterBy: DyFM_DBFilter<T>,
671
- narrowByDependencyIds?: string[],
672
- narrowByDependencyKey?: string,
673
- findDeleted?: boolean
674
- ): Promise<T[]> {
675
- const filter = {};
676
-
677
- if (0 < narrowByDependencyIds.length) {
678
- if (!this.depKeys.length) {
679
- throw new DyFM_Error({
680
- ...this._getDefaultErrorSettings(
681
- 'searchData',
682
- new Error(
683
- `dependencyDataIdKey not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
684
- )
685
- ),
686
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-SD0`,
687
- });
688
- }
689
-
690
- if (!narrowByDependencyKey) {
691
- if (this.depKeys.length === 1) {
692
- narrowByDependencyKey = this.depKeys[0];
693
- } else {
694
- throw new DyFM_Error({
695
- ...this._getDefaultErrorSettings(
696
- 'searchData',
697
- new Error(`dependencyKey is missing! (${this.dataParams.dataName}) (NTS DB)`),
698
- ),
699
- });
700
- }
701
- }
702
-
703
- filter[narrowByDependencyKey] = { $in: narrowByDependencyIds };
704
- }
705
-
706
- Object.values(this.dataParams.properties).forEach(
707
- (modelParam: DyFM_DataProperty_Params<any, T>): void => {
708
- if (
709
- (filterBy[modelParam.key] !== null && filterBy[modelParam.key] !== undefined) ||
710
- filterBy[modelParam.key + 'Range']
711
- ) {
712
- if (modelParam.key.includes('Range') || modelParam.type.includes('[]')) {
713
- // inverz search filter (for Range and Array functions)
714
- if (modelParam.key.includes('Range')) {
715
- const searchParamKeyWithoutRange = modelParam.key.split('Range')[0];
716
-
717
- if (
718
- filterBy[searchParamKeyWithoutRange] !== null &&
719
- filterBy[searchParamKeyWithoutRange] !== undefined
720
- ) {
721
- filter[modelParam.key] = {
722
- from: { $lte: filterBy[searchParamKeyWithoutRange] },
723
- to: { $gte: filterBy[searchParamKeyWithoutRange] },
724
- };
725
- }
726
- } else {
727
- if (
728
- filterBy[modelParam.key] !== null &&
729
- filterBy[modelParam.key] !== undefined
730
- ) {
731
- filter[modelParam.key] = { $in: filterBy[modelParam.key] };
732
- }
733
- }
734
- } else {
735
- // basic search filter
736
- if (filterBy[modelParam.key + 'Range']) {
737
- if (
738
- filterBy[modelParam.key + 'Range'].from ||
739
- filterBy[modelParam.key + 'Range'].to
740
- ) {
741
- filter[modelParam.key] = {};
742
-
743
- if (filterBy[modelParam.key + 'Range'].from) {
744
- filter[modelParam.key].$gte = filterBy[modelParam.key + 'Range'].from;
745
- }
746
-
747
- if (filterBy[modelParam.key + 'Range'].to) {
748
- filter[modelParam.key].$lte = filterBy[modelParam.key + 'Range'].to;
749
- }
750
- }
751
- } else if (
752
- filterBy[modelParam.key] !== null &&
753
- filterBy[modelParam.key] !== undefined
754
- ) {
755
- if (filterBy[modelParam.key].lenght > 0) {
756
- filter[modelParam.key] = { $in: filterBy[modelParam.key] };
757
- }
758
- }
759
- }
760
- }
761
- }
762
- );
763
-
764
- let dataList: T[] = await this.dataModel
765
- .find(filter)
766
- .then((res): T[] => res as T[] ?? [])
767
- .catch((error): void => {
768
- throw new DyFM_Error({
769
- ...this._getDefaultErrorSettings('searchData', error),
770
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-SD1`,
771
- additionalContent: { filterBy, narrowByDependencyIds },
772
- message:
773
- `search "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
774
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
775
- });
776
- });
777
-
778
- if (!findDeleted && (filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined) {
779
- dataList = dataList.filter((data: T): boolean => !data._deleted);
780
- }
781
-
782
- return dataList.map((data: T): T => this.stringifyDataId(data, 'searchData'));
783
- }
784
-
785
- // ----------------------------------------------------------------------------------
786
- // ----------------------------------------------------------------------------------
787
- // ----------------------------------------------------------------------------------
788
- // DIRECT Basic MONGOOSE FUNCTIONS (with error handlings)
789
-
790
- /**
791
- * Find the data first by any of its parameters,
792
- * !!!: throws error if not found (errorCode on not found: NTS-DBS-FO1)
793
- *
794
- * @param filterBy if you can, use unique parameters for find!
795
- *
796
- * @example
797
- * // by email:
798
- * { email: email }
799
- * //
800
- * @example
801
- * // or by id that is in list:
802
- * { userIds: { $in: this.userId } }
803
- * // or by userIds:
804
- * { userId: { $in: userIds } }
805
- * //
806
- * @example
807
- * // or by number or Date that is Greater Than AND Less Than:
808
- * { points: { $gt: 2, $lt: 14 } }
809
- * // further tools (syntax matches with $gt):
810
- * $eq: // Matches values that are EQual to a specified value.
811
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
812
- * $lte: // Matches values that are Less Than or Equal to a specified value.
813
- * $ne: // Matches all values that are Not Equal to a specified value.
814
- * $nin: // Matches None of the values specified IN an array.
815
- * //
816
- * @returns {T} data: T
817
- */
818
- async findOne(filterBy: DyFM_DBFilter<T>): Promise<T> {
819
- const data: T = await this.dataModel
820
- .findOne(filterBy)
821
- .then((res): T => res as T ?? null)
822
- .catch((error): void => {
823
- throw new DyFM_Error({
824
- ...this._getDefaultErrorSettings('findOne', error),
825
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FO0`,
826
- additionalContent: { filterBy },
827
- message:
828
- `findOne "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
829
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
830
- });
831
- });
832
-
833
- return this.stringifyDataId(data, 'findOne');
834
- }
835
-
836
- /**
837
- * #MONGOOSE FUNCTION
838
- * Find the data first by any of its parameters,
839
- * !!!: throws error if not found (errorCode on not found: NTS-DBS-F1)
840
- *
841
- * @param filterBy if you can, use unique parameters for find!
842
- *
843
- * @example
844
- * // by email:
845
- * { email: email }
846
- * //
847
- * @example
848
- * // or by id that is in list:
849
- * { userIds: { $in: this.userId } }
850
- * // or by userIds:
851
- * { userId: { $in: userIds } }
852
- * //
853
- * @example
854
- * // or by number or Date that is Greater Than AND Less Than:
855
- * { points: { $gt: 2, $lt: 14 } }
856
- * // further tools (syntax matches with $gt):
857
- * $eq: // Matches values that are EQual to a specified value.
858
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
859
- * $lte: // Matches values that are Less Than or Equal to a specified value.
860
- * $ne: // Matches all values that are Not Equal to a specified value.
861
- * $nin: // Matches None of the values specified IN an array.
862
- * //
863
- * @param options BFR-008: opcionalis projection/limit/sort — DB-szinten szukit (a nagy mezok be sem toltodnek)
864
- * @returns {T[]} dataList: T[]
865
- */
866
- async find(filterBy: DyFM_DBFilter<T>, findDeleted?: boolean, options?: DyNTS_DBQueryOptions<T>): Promise<T[]> {
867
- // BFR-OVERSEER-008 — options megadasakor a soft-delete szures QUERY-szintre kerul: limit mellett a
868
- // memoriabeli post-filter hibas darabszamot adna, projekcio mellett (kihagyott `_deleted` mezovel)
869
- // hibasan atengedne a torolt dokumentumokat. A `_deleted` soft-delete-kor `new Date()`, egyebkent
870
- // HIANYZIK → a Mongo `_deleted: null` (missing VAGY null) a post-filter `!data._deleted` ekvivalense.
871
- const deletedGuardInQuery: boolean =
872
- !!options && !findDeleted && (filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined;
873
- const effectiveFilter: DyFM_DBFilter<T> = deletedGuardInQuery
874
- ? { ...(filterBy as DyFM_DBFilterSimple<T>), _deleted: null } as unknown as DyFM_DBFilter<T>
875
- : filterBy;
876
-
877
- // A szukites (select/sort/limit) DB-szinten tortenik → a nagy mezok be sem toltodnek a heap-be.
878
- let query = this.dataModel.find(effectiveFilter);
879
- if (options?.projection) { query = query.select(options.projection); }
880
- if (options?.sort) { query = query.sort(options.sort); }
881
- if (options?.limit) { query = query.limit(options.limit); }
882
-
883
- let dataList: T[] = await query
884
- .then((res): T[] => res as T[] ?? [])
885
- .catch((error): void => {
886
- throw new DyFM_Error({
887
- ...this._getDefaultErrorSettings('find', error),
888
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-F0`,
889
- additionalContent: { filterBy },
890
- message:
891
- `find "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
892
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
893
- });
894
- });
895
-
896
- if (!findDeleted && !deletedGuardInQuery && (filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined) {
897
- dataList = dataList.filter((data: T): boolean => !data._deleted);
898
- }
899
-
900
- return dataList.map((data: T): T => this.stringifyDataId(data, 'find'));
901
- }
902
-
903
- /**
904
- * #MONGOOSE FUNCTION
905
- * Find the data first by any of its parameters
906
- * WARNING: This function will not gives you back the total number of data in the database!
907
- *
908
- * @param filterBy if you can, use unique parameters for find!
909
- *
910
- * @example
911
- * // by email:
912
- * { email: email }
913
- * //
914
- * @example
915
- * // or by id that is in list:
916
- * { userIds: { $in: this.userId } }
917
- * // or by userIds:
918
- * { userId: { $in: userIds } }
919
- * //
920
- * @example
921
- * // or by number or Date that is Greater Than AND Less Than:
922
- * { points: { $gt: 2, $lt: 14 } }
923
- * // further tools (syntax matches with $gt):
924
- * $eq: // Matches values that are EQual to a specified value.
925
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
926
- * $lte: // Matches values that are Less Than or Equal to a specified value.
927
- * $ne: // Matches all values that are Not Equal to a specified value.
928
- * $nin: // Matches None of the values specified IN an array.
929
- * //
930
- * @param page page
931
- * @param pageSize pageSize
932
- * @param sort
933
- * @example
934
- * // by dateTime (this uses the basic sort function):
935
- * { dateTime: -1 }
936
- * //
937
- * @returns {T[]} dataList: T[]
938
- */
939
- async findWithPaging(
940
- filterBy: DyFM_DBFilter<T>,
941
- page: number,
942
- pageSize: number,
943
- sort?: DyFM_DBSort<T>
944
- ): Promise<T[]> {
945
- /* if (filterBy['_deleted'] === undefined) {
946
- filterBy['_deleted'] = null;
947
- } */
948
-
949
- const dataList: T[] = await this.dataModel
950
- .find(filterBy)
951
- .sort(sort)
952
- .skip(page * pageSize)
953
- .limit(pageSize)
954
- .then((res): T => res ?? [])
955
- .catch((error): void => {
956
- throw new DyFM_Error({
957
- ...this._getDefaultErrorSettings('findWithPaging', error),
958
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-WP0`,
959
- additionalContent: { filterBy, page, pageSize, sort },
960
- message:
961
- `findWithPaging "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
962
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
963
- });
964
- });
965
-
966
- /* if ((filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined) {
967
- dataList = dataList.filter((data: T): boolean => !data._deleted);
968
- } */
969
-
970
- return dataList.map((data: T): T => this.stringifyDataId(data, 'find'));
971
- }
972
-
973
- /**
974
- * #MONGOOSE FUNCTION
975
- * Find data by _id and update
976
- *
977
- * @param id id
978
- * @param update update
979
- * @returns data
980
- */
981
- async findByIdAndUpdate(
982
- id: string,
983
- update: DyNTS_DBUpdate<T>,
984
- issuer: string,
985
- dontUpdateModified?: boolean
986
- ): Promise<T> {
987
- if (this.dataParams.forbidModify) {
988
- await this.modifyThrowMethod(update, issuer);
989
- }
990
-
991
- if (!dontUpdateModified) {
992
- update.__lastModified = new Date();
993
- update.__lastModifiedBy = issuer;
994
- }
995
-
996
- const data: T = await this.dataModel
997
- .findByIdAndUpdate(id, update)
998
- .then((res): T => res?.toObject() as T ?? null)
999
- .catch((error): void => {
1000
- throw new DyFM_Error({
1001
- ...this._getDefaultErrorSettings('findByIdAndUpdate', error, issuer),
1002
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FIU0`,
1003
- additionalContent: { id, update },
1004
- message:
1005
- `findByIdAndUpdate "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1006
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1007
- issuer,
1008
- });
1009
- });
1010
-
1011
- return this.stringifyDataId(data, 'findByIdAndUpdate');
1012
- }
1013
-
1014
- /**
1015
- * #MONGOOSE FUNCTION
1016
- * Atomi compare-and-set: filter-alapú find + update EGY műveletben, a MÓDOSÍTOTT dokumentum
1017
- * visszaadásával (BFR-FDPTOKENSERVICE-006).
1018
- *
1019
- * A `findByIdAndUpdate` (id-only, nem filterezhető) és az `updateOne` (filterezhető, de void —
1020
- * nem különíthető el a winner/loser konkurens state-átmenetnél) egyike sem elég CAS-hoz: egy
1021
- * state-machine `transitionStatus`-jellegű átmenetnél a filter a FELTÉTEL (pl. `{_id, status:
1022
- * 'locked'}`), és a visszatérő érték dönti el, hogy EZ a hívás nyerte-e az átmenetet.
1023
- * `null` = nincs match (a feltétel már nem áll — a versenytárs nyert / state-collision).
1024
- *
1025
- * A `__lastModified`/`forbidModify` szemantika a `findByIdAndUpdate`-tel EGYEZŐ (egységes
1026
- * update-viselkedés a base-ben); a `{ new: true }` a MÓDOSÍTOTT dokumentumot adja vissza.
1027
- */
1028
- async findOneAndUpdate(
1029
- filterBy: DyFM_DBFilter<T>,
1030
- update: DyNTS_DBUpdate<T>,
1031
- issuer: string,
1032
- dontUpdateModified?: boolean
1033
- ): Promise<T | null> {
1034
- if (this.dataParams.forbidModify) {
1035
- await this.modifyThrowMethod(update, issuer);
1036
- }
1037
-
1038
- if (!dontUpdateModified) {
1039
- update.__lastModified = new Date();
1040
- update.__lastModifiedBy = issuer;
1041
- }
1042
-
1043
- const data: T | null = await this.dataModel
1044
- .findOneAndUpdate(filterBy, update, { new: true })
1045
- .then((res): T | null => res?.toObject() as T ?? null)
1046
- .catch((error): never => {
1047
- throw new DyFM_Error({
1048
- ...this._getDefaultErrorSettings('findOneAndUpdate', error, issuer),
1049
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FOU0`,
1050
- additionalContent: { filterBy, update },
1051
- message:
1052
- `findOneAndUpdate "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1053
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1054
- issuer,
1055
- });
1056
- });
1057
-
1058
- // no-match (CAS lost / feltétel nem áll): a null ÉRVÉNYES eredmény, nem hiba
1059
- if (!data) {
1060
- return null;
1061
- }
1062
-
1063
- return this.stringifyDataId(data, 'findOneAndUpdate');
1064
- }
1065
-
1066
- /**
1067
- * #MONGOOSE FUNCTION
1068
- * Find the data first by any of its parameters
1069
- *
1070
- * @param filter This uses the basic Mongoose updateOne.
1071
- * If you can, use unique parameters for find!
1072
- * @example
1073
- * // by email:
1074
- * { email: email }
1075
- * //
1076
- * @example
1077
- * // or by id that is in list:
1078
- * { userIds: { $in: this.userId } }
1079
- * // or by userIds:
1080
- * { userId: { $in: userIds } }
1081
- * //
1082
- * @example
1083
- * // or by number or Date that is Greater Than AND Less Than:
1084
- * { points: { $gt: 2, $lt: 14 } }
1085
- * // further tools (syntax matches with $gt):
1086
- * $eq: // Matches values that are EQual to a specified value.
1087
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
1088
- * $lte: // Matches values that are Less Than or Equal to a specified value.
1089
- * $ne: // Matches all values that are Not Equal to a specified value.
1090
- * $nin: // Matches None of the values specified IN an array.
1091
- * //
1092
- *
1093
- * @param update this uses the basic Mongoose updateOne
1094
- * @example
1095
- * // increase a specific value (here by 15):
1096
- * { $inc: { popularity: 15 } }
1097
- * //
1098
- * @example
1099
- * // or add element to a list:
1100
- * { $push: { reactions: this.newReaction }
1101
- * // or add multiple elements to a list
1102
- * { $push: { schedule: {$each: [ monday, tuesday, wednesday ] } } }
1103
- * //
1104
- * @example
1105
- * // or all at once
1106
- * {
1107
- * $inc: { popularity: this.newVote.amount },
1108
- * emailVerified: true,
1109
- * $push: { reactions: this.newReaction }
1110
- * }
1111
- * // further tools (syntax matches with $inc):
1112
- * $currentDate: // Sets the value of a field to current date, either as a Date or a Timestamp.
1113
- * $min: // Only updates the field if the specified value is less than the existing field value.
1114
- * $max: // Only updates the field if the specified value is greater than the existing field value.
1115
- * $mul: // Multiplies the value of the field by the specified amount.
1116
- * $rename: // Renames a field.
1117
- * $unset: // Removes the specified field from a document. (set: "" to value)
1118
- * //
1119
- */
1120
- async updateOne(
1121
- filterBy: DyFM_DBFilter<T>,
1122
- update: DyNTS_DBUpdate<T>,
1123
- issuer: string,
1124
- dontUpdateModified?: boolean
1125
- ): Promise<void> {
1126
- if (this.dataParams.forbidModify) {
1127
- await this.modifyThrowMethod(update, issuer);
1128
- }
1129
-
1130
- if (!dontUpdateModified) {
1131
- update.__lastModified = new Date();
1132
- update.__lastModifiedBy = issuer;
1133
- }
1134
-
1135
- await this.dataModel
1136
- .updateOne(filterBy, update)
1137
- .catch((error): void => {
1138
- throw new DyFM_Error({
1139
- ...this._getDefaultErrorSettings('updateOne', error, issuer),
1140
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-UO0`,
1141
- additionalContent: { filterBy, update },
1142
- message:
1143
- `updateOne "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1144
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1145
- issuer,
1146
- });
1147
- });
1148
- }
1149
-
1150
- /**
1151
- * #MONGOOSE FUNCTION
1152
- * update one parameter by a specific
1153
- *
1154
- * @param filter This uses the basic Mongoose updateMany.
1155
- * @example
1156
- * // by email:
1157
- * { email: email }
1158
- * //
1159
- * @example
1160
- * // or by id that is in list:
1161
- * { userIds: { $in: this.userId } }
1162
- * // or by userIds:
1163
- * { userId: { $in: userIds } }
1164
- * //
1165
- * @example
1166
- * // or by number or Date that is Greater Than AND Less Than:
1167
- * { points: { $gt: 2, $lt: 14 } }
1168
- * // further tools (syntax matches with $gt):
1169
- * $eq: // Matches values that are EQual to a specified value.
1170
- * $gte: // Matches values that are Greater Than OR Equal to a specified value.
1171
- * $lte: // Matches values that are Less Than or Equal to a specified value.
1172
- * $ne: // Matches all values that are Not Equal to a specified value.
1173
- * $nin: // Matches None of the values specified IN an array.
1174
- * //
1175
- *
1176
- * @param update this uses the basic Mongoose updateOne
1177
- * @example
1178
- * // increase a specific value (here by 15):
1179
- * { $inc: { popularity: 15 } }
1180
- * //
1181
- * @example
1182
- * // or add element to a list:
1183
- * { $push: { reactions: this.newReaction }
1184
- * // or add multiple elements to a list
1185
- * { $push: { schedule: {$each: [ monday, tuesday, wednesday ] } } }
1186
- * //
1187
- * @example
1188
- * // or all at once
1189
- * {
1190
- * $inc: { popularity: this.newVote.amount },
1191
- * emailVerified: true,
1192
- * $push: { reactions: this.newReaction }
1193
- * }
1194
- * // further tools (syntax matches with $inc):
1195
- * $currentDate: // Sets the value of a field to current date, either as a Date or a Timestamp.
1196
- * $min: // Only updates the field if the specified value is less than the existing field value.
1197
- * $max: // Only updates the field if the specified value is greater than the existing field value.
1198
- * $mul: // Multiplies the value of the field by the specified amount.
1199
- * $rename: // Renames a field.
1200
- * $unset: // Removes the specified field from a document. (set: "" to value)
1201
- * //
1202
- */
1203
- async updateMany(
1204
- filterBy: DyFM_DBFilter<T>,
1205
- update: DyNTS_DBUpdate<T>,
1206
- issuer: string,
1207
- dontUpdateModified?: boolean
1208
- ): Promise<void> {
1209
- if (this.dataParams.forbidModify) {
1210
- await this.modifyThrowMethod(update, issuer);
1211
- }
1212
-
1213
- if (!dontUpdateModified) {
1214
- update.__lastModified = new Date();
1215
- update.__lastModifiedBy = issuer;
1216
- }
1217
-
1218
- await this.dataModel
1219
- .updateMany(filterBy, update)
1220
- .catch((error): void => {
1221
- throw new DyFM_Error({
1222
- ...this._getDefaultErrorSettings('updateMany', error, issuer),
1223
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-UM0`,
1224
- additionalContent: { filterBy, update },
1225
- message:
1226
- `updateMany "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1227
- `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1228
- issuer,
1229
- });
1230
- });
1231
- }
1232
-
1233
- /**
1234
- * {
1235
- "mappings": {
1236
- "dynamic": true,
1237
- "fields": {
1238
- "embedding": {
1239
- "type": "knnVector",
1240
- "dimensions": 768
1241
- }
1242
- }
1243
- }
1244
- }
1245
- */
1246
- /**
1247
- *
1248
- * @param set db.collection.aggregate([
1249
- {
1250
- $vectorSearch: {
1251
- index: "index_neve",
1252
- queryVector: [a keresett embedding],
1253
- path: "title.embedding",
1254
- numCandidates: 100,
1255
- limit: 5
1256
- }
1257
- },
1258
- {
1259
- $vectorSearch: {
1260
- index: "index_neve",
1261
- queryVector: [a keresett embedding],
1262
- path: "description.embedding",
1263
- numCandidates: 100,
1264
- limit: 5
1265
- }
1266
- }
1267
- ]);
1268
- * @returns
1269
- */
1270
- async aggregate(set: any) {
1271
- return this.dataModel.aggregate(set);
1272
- }
1273
-
1274
- // ----------------------------------------------------------------------------------
1275
- // ----------------------------------------------------------------------------------
1276
- // ----------------------------------------------------------------------------------
1277
- // PRIVATE FUNCTIONS
1278
-
1279
- private stringifyDataId(data: T, fnName: string): T {
1280
- if (data?._id && (typeof data._id !== 'string' || typeof data._id === 'object')) {
1281
- data._id = `${data._id}`;
1282
-
1283
- if (typeof data._id !== 'string' || typeof data._id === 'object') {
1284
- data = JSON.parse(JSON.stringify(data));
1285
-
1286
- if (typeof data._id !== 'string' || typeof data._id === 'object') {
1287
- DyFM_Log.error(
1288
- `data._id stringifying failed! Please notfiy the DynamoNTS developers! (${fnName})`,
1289
- new Error()
1290
- );
1291
- }
1292
- }
1293
- }
1294
-
1295
- return data;
1296
- }
1297
-
1298
- private _getDefaultErrorSettings(
1299
- fnName: string,
1300
- error: DyFM_AnyError,
1301
- issuer?: string
1302
- ): DyFM_Error_Settings {
1303
- return {
1304
- status: (error as DyFM_Error)?.___status ?? 500,
1305
- message: (error as Error)?.message ??
1306
- (error as DyFM_Error)?._message ??
1307
- `${fnName} was UNSUCCESSFUL (NTS-DB)`,
1308
- addECToUserMsg: !(error as DyFM_Error)?.__userMessage,
1309
- userMessage: (error as DyFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
1310
- issuer: issuer,
1311
- issuerService: this.serviceName,
1312
- error: error,
1313
- };
1314
- }
1315
-
1316
- // ----------------------------------------------------------------------------------
1317
- // PRIVATE BUILD FUNCTIONS
1318
-
1319
- /**
1320
- * builds and returns mongoose schema
1321
- * @returns schema
1322
- */
1323
- private getSchema(): mongoose.Schema {
1324
- this.dataParams.properties = this.addMetadataToProperties(this.dataParams.properties);
1325
-
1326
- if (this.dataParams.dataName.includes(DyNTS_archiveSuffix)) {
1327
- this.dataParams.properties = this.addArchiveMetadataToProperties(this.dataParams.properties);
1328
- }
1329
-
1330
- const schemaSettings: any = this.buildMongooseSchemaSettingsObjByModelParams(
1331
- this.dataParams.properties
1332
- );
1333
-
1334
- /* schema = this.addMetadataToSchema(schema); */
1335
-
1336
- /* if (this.dataParams.dataName.includes(DyNTS_archiveSuffix)) {
1337
- schema = this.addArchiveMetadataToSchema(schema);
1338
- } */
1339
-
1340
- if (schemaSettings['_id']) {
1341
- delete schemaSettings['_id'];
1342
- }
1343
-
1344
- return new Schema(schemaSettings);
1345
- }
1346
-
1347
- /**
1348
- * builds mongoose schema building settings object by dynamoDataModelParamsList
1349
- * @param properties DynamoNTSDataPropertyParams
1350
- * @returns mongoose schema object
1351
- */
1352
- private buildMongooseSchemaSettingsObjByModelParams(properties: DyFM_DataProperties<T>): any {
1353
- const schemaSettingsObj = {};
1354
-
1355
- /* if (!properties) {
1356
- properties = this.dataParams.properties;
1357
- } */
1358
-
1359
- Object.values(properties).forEach((property: DyFM_DataProperty_Params<any, T>): void => {
1360
- if (!property) {
1361
- DyFM_Log.warn(`property is undefined on "${this.dataParams.dataName}" (NTS DB)`);
1362
-
1363
- return;
1364
- }
1365
-
1366
- if (!property.key) {
1367
- const missingKeys = Object.keys(properties).filter((key: string) => !properties[key].key);
1368
-
1369
- throw new DyFM_Error({
1370
- ...this._getDefaultErrorSettings(
1371
- 'buildMongooseSchemaByModelParams',
1372
- new Error(
1373
- `property.key is undefined on "${this.dataParams.dataName}" (NTS DB) ` +
1374
- `(keys: ${Object.keys(properties).join(', ')}) ` +
1375
- `(missing keys: ${missingKeys.join(', ')})`
1376
- )
1377
- ),
1378
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-BMSBP0`,
1379
- additionalContent: {
1380
- property: property,
1381
- dataParams: this.dataParams,
1382
- missingKeys: missingKeys,
1383
- },
1384
- });
1385
- }
1386
-
1387
- if (property.forbidden) {
1388
- return;
1389
- }
1390
-
1391
- const beType = this.getBEType(property.type as DyFM_BasicProperty_Type);
1392
-
1393
- /* TODO if (beType === Array && property.archiveable && !property.archiveListAfter) {
1394
- property.archiveListAfter = DyNTS_global_settings.archiveListAfter;
1395
- } */
1396
-
1397
- if (
1398
- beType !== Object ||
1399
- !property?.subObjectParams ||
1400
- (property?.subObjectParams &&
1401
- Object.keys(property.subObjectParams).length == 0)
1402
- ) {
1403
- schemaSettingsObj[property.key] = {
1404
- type: beType,
1405
- };
1406
-
1407
- if (property.index) {
1408
- schemaSettingsObj[property.key].index = true;
1409
- }
1410
-
1411
- if (property.unique) {
1412
- schemaSettingsObj[property.key].unique = true;
1413
- }
1414
-
1415
- if (property.required) {
1416
- schemaSettingsObj[property.key].required = true;
1417
- }
1418
-
1419
- if (property.minlength) {
1420
- schemaSettingsObj[property.key].minlength = property.minlength;
1421
- }
1422
-
1423
- if (property.maxlength) {
1424
- schemaSettingsObj[property.key].maxlength = property.maxlength;
1425
- }
1426
- } else {
1427
- schemaSettingsObj[property.key] = this.buildMongooseSchemaSettingsObjByModelParams(
1428
- property.subObjectParams
1429
- );
1430
- }
1431
- });
1432
-
1433
- return schemaSettingsObj;
1434
- }
1435
-
1436
- private getBEType(
1437
- type: DyFM_BasicProperty_Type
1438
- ): string | number | boolean | object | Function | Array<any> | Date {
1439
- switch (type) {
1440
- case DyFM_BasicProperty_Type.string:
1441
- return String;
1442
-
1443
- case DyFM_BasicProperty_Type.number:
1444
- return Number;
1445
-
1446
- case DyFM_BasicProperty_Type.boolean:
1447
- return Boolean;
1448
-
1449
- case DyFM_BasicProperty_Type.date:
1450
- return Date;
1451
-
1452
- case DyFM_BasicProperty_Type.object:
1453
- return Object;
1454
-
1455
- case DyFM_BasicProperty_Type.array:
1456
- return Array;
1457
-
1458
- case DyFM_BasicProperty_Type.function:
1459
- return Function;
1460
-
1461
- default:
1462
- DyFM_Log.H_info('wtf', DyFM_Object.cleanObject(this.dataParams));
1463
-
1464
- throw new DyFM_Error({
1465
- error: new Error(
1466
- `Invalid property type: "${type}" (${this.dataParams.dataName})` +
1467
- (this.dataParams.constructed?.() ? '' : ('\nThe dataParams is not constructed properly! \n' +
1468
- 'Use the DyFM_DataModel_Params.constructor to construct it properly!'))
1469
- ),
1470
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GTP0`,
1471
- additionalContent: { type: type, dataParams: this.dataParams },
1472
- __localStack: this.dataParams.stackLocation,
1473
- });
1474
- }
1475
- /* switch (type.toLocaleLowerCase()) {
1476
- case DyFM_BasicProperty_Type.string:
1477
- case 'string':
1478
- return String;
1479
-
1480
- case DyFM_BasicProperty_Type.number:
1481
- case 'number':
1482
- return Number;
1483
-
1484
- case DyFM_BasicProperty_Type.boolean:
1485
- case 'boolean':
1486
- return Boolean;
1487
-
1488
- case DyFM_BasicProperty_Type.date:
1489
- case 'date':
1490
- return Date;
1491
-
1492
- case DyFM_BasicProperty_Type.object:
1493
- case 'object':
1494
- return Object;
1495
-
1496
- case DyFM_BasicProperty_Type.array:
1497
- case 'array':
1498
- return Array;
1499
-
1500
- default:
1501
- if (type.includes('[]') || type.includes('array')) {
1502
- return Array;
1503
- } else if (type.includes('=>') || type.includes('function')) {
1504
- return Function;
1505
- } else {
1506
- return Object;
1507
- }
1508
- } */
1509
- }
1510
-
1511
- /**
1512
- * adds dynamo metadata settings to any mongoose schema building settings object
1513
- * @param schema schema to update
1514
- * @returns updated schema
1515
- */
1516
- /* private addMetadataToSchema(schema: any): any {
1517
- schema.__created = { type: Date };
1518
- schema.__createdBy = { type: String };
1519
- schema.__lastModified = { type: Date };
1520
- schema.__lastModifiedBy = { type: String };
1521
-
1522
- schema._deleted = { type: Date };
1523
- schema._deletedBy = { type: String };
1524
-
1525
- return schema;
1526
- } */
1527
-
1528
- /**
1529
- * adds dynamo metadata settings to any mongoose schema building settings object
1530
- * @param properties properties to update
1531
- * @returns updated properties
1532
- */
1533
- private addMetadataToProperties(properties: DyFM_DataProperties<T>): DyFM_DataProperties<T> {
1534
- // TOD: ezek a kikommentelt "required: true"-k kellenek, csak félő, hogy gondokat okoznak a
1535
- // jelenlegi rendszerekben, ezért akkor kell majd visszarakni, ha lesz tesztelői ÉS fejlesztői kapacitás rá
1536
- if (!properties.__created) {
1537
- properties.__created = {
1538
- key: '__created', type: DyFM_BasicProperty_Type.date/* , required: true */,
1539
- };
1540
- }
1541
-
1542
- if (!properties.__createdBy) {
1543
- properties.__createdBy = {
1544
- key: '__createdBy', type: DyFM_BasicProperty_Type.string/* , required: true */,
1545
- };
1546
- }
1547
-
1548
- if (!properties.__lastModified) {
1549
- properties.__lastModified = {
1550
- key: '__lastModified', type: DyFM_BasicProperty_Type.date/* , required: true */,
1551
- };
1552
- }
1553
-
1554
- if (!properties.__lastModifiedBy) {
1555
- properties.__lastModifiedBy = {
1556
- key: '__lastModifiedBy', type: DyFM_BasicProperty_Type.string/* , required: true */,
1557
- };
1558
- }
1559
-
1560
- if (!properties._deleted) {
1561
- properties._deleted = {
1562
- key: '_deleted', type: DyFM_BasicProperty_Type.date,
1563
- };
1564
- }
1565
-
1566
- if (!properties._deletedBy) {
1567
- properties._deletedBy = {
1568
- key: '_deletedBy', type: DyFM_BasicProperty_Type.string,
1569
- };
1570
- }
1571
-
1572
- if (!properties._archived) {
1573
- properties._archived = {
1574
- key: '_archived', type: DyFM_BasicProperty_Type.date,
1575
- };
1576
- }
1577
-
1578
- return properties;
1579
- }
1580
-
1581
- /* private addArchiveMetadataToSchema(schema: any): any {
1582
- schema._originalId = { type: String, required: true, index: true, unique: true };
1583
- schema._archived = { type: Date, required: true };
1584
-
1585
- return schema;
1586
- } */
1587
-
1588
- private addArchiveMetadataToProperties(
1589
- properties: DyFM_DataProperties<T>
1590
- ): DyFM_DataProperties<T> {
1591
- if (!properties._originalId) {
1592
- properties._originalId = {
1593
- key: '_originalId', type: DyFM_BasicProperty_Type.string,
1594
- required: true, index: true, unique: true,
1595
- };
1596
- }
1597
-
1598
- if (!properties._archived) {
1599
- properties._archived = {
1600
- key: '_archived', type: DyFM_BasicProperty_Type.date,
1601
- required: true,
1602
- };
1603
- } else if (properties._archived.required === undefined) {
1604
- properties._archived.required = true;
1605
- }
1606
-
1607
- return properties;
1608
- }
1609
-
1610
- /**
1611
- * sets depDataKey
1612
- */
1613
- private lookForDependencyDataSettings(): void {
1614
- const dependencyParams: DyFM_DataProperty_Params<any, T>[] =
1615
- Object.values(this.dataParams.properties).filter(
1616
- (modelParams: DyFM_DataProperty_Params<any, T>): boolean =>
1617
- Boolean(modelParams.dependencyDataName)
1618
- );
1619
-
1620
- if (dependencyParams) {
1621
- this.depKeys.push(...dependencyParams.map(
1622
- (dependencyParam: DyFM_DataProperty_Params<any, T>): string => dependencyParam.key
1623
- ));
1624
- }
1625
- }
1626
-
1627
- private async deleteThrowMethod(data: any, issuer?: string): Promise<void> {
1628
- throw new DyFM_Error({
1629
- error: new Error(`Forbidden to delete any data! (${this.dataParams.dataName})`),
1630
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CDAD`,
1631
- additionalContent: { dataParams: this.dataParams, data: data },
1632
- issuer: issuer,
1633
- });
1634
- };
1635
-
1636
- private async modifyThrowMethod(data: any, issuer?: string): Promise<void> {
1637
- throw new DyFM_Error({
1638
- error: new Error(`Forbidden to modify any data! (${this.dataParams.dataName})`),
1639
- errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CDAD`,
1640
- additionalContent: { dataParams: this.dataParams, data: data },
1641
- issuer: issuer,
1642
- });
1643
- }
1644
- }
1
+
2
+ import * as mongoose from 'mongoose';
3
+ import { Schema } from 'mongoose';
4
+
5
+ import {
6
+ DyFM_AnyError,
7
+ DyFM_BasicProperty_Type,
8
+ DyFM_DataModel_Params,
9
+ DyFM_DataProperties,
10
+ DyFM_DataProperty_Params,
11
+ DyFM_DBFilter, DyFM_DBFilterSimple, DyFM_DBSort,
12
+ DyFM_Error,
13
+ DyFM_Error_Settings, DyFM_ErrorLevel,
14
+ DyFM_Log,
15
+ DyFM_Metadata,
16
+ DyFM_Object
17
+ } from '@futdevpro/fsm-dynamo';
18
+ import { DyNTS_archiveSuffix } from '../../_collections/archive.util';
19
+ import { DyNTS_DBUpdate } from '../../_models/types/db-update.type';
20
+ import { DyNTS_DBQueryOptions } from '../../_models/interfaces/db-query-options.interface';
21
+ import { DyNTS_global_settings } from '../../_collections/global-settings.const';
22
+
23
+ /**
24
+ * DB Service for MongoDB
25
+ */
26
+ export class DyNTS_DBService<T extends DyFM_Metadata> {
27
+
28
+ serviceName: string;
29
+
30
+ dataModel/* : mongoose.Model<T> */; // = mongoose.model(this.dataParams.dataName, this.getSchema());
31
+
32
+ /* private depDataName: string; */
33
+ private readonly depKeys: string[] = [];
34
+
35
+ defaultErrorUserMsg =
36
+ `We encountered an unhandled DB Error, ` +
37
+ `\nplease contact the responsible development team.`;
38
+
39
+ /**
40
+ * @param dataName name the model
41
+ * @param typeSample sample data for scheme creation (dont include DyFM_Metadata!)
42
+ * @param schemaSettings additional settings for specific parameters as unique, required, minlength or maxlength
43
+ * schemaSettings also MUST contain specific types that differs from the listed above (Array, Date)
44
+ */
45
+ constructor(
46
+ public dataParams: DyFM_DataModel_Params<T>
47
+ ){
48
+ try {
49
+ this.serviceName = this.constructor?.name;
50
+
51
+ if (!this.dataParams.dataName || typeof this.dataParams.dataName !== 'string') {
52
+ throw new Error(
53
+ `dbName not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
54
+ );
55
+ }
56
+
57
+ if (!this.dataParams.constructed?.()) {
58
+ throw new DyFM_Error({
59
+ error: new Error(
60
+ `DataModelParams is not constructed properly! (${this.dataParams.dataName}) ` +
61
+ `Use the DyFM_DataModel_Params.constructor to construct it properly! (NTS DB)`
62
+ ),
63
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-C01`,
64
+ additionalContent: { dataParams: this.dataParams },
65
+ __localStack: this.dataParams.stackLocation,
66
+ });
67
+ }
68
+
69
+ try {
70
+ this.dataModel = mongoose.model(this.dataParams.dataName, this.getSchema());
71
+ } catch (error) {
72
+ if (mongoose.models[this.dataParams.dataName]) {
73
+ this.dataModel = mongoose.models[this.dataParams.dataName];
74
+ } else {
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ this.lookForDependencyDataSettings();
80
+ } catch (error) {
81
+ throw new DyFM_Error({
82
+ message:
83
+ `DyNTS_DBService construction failed! "${dataParams.dataName}" - "${this.serviceName}"`,
84
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-C00`,
85
+ level: DyFM_ErrorLevel.critical,
86
+ additionalContent: { dataParams: this.dataParams },
87
+ error,
88
+ });
89
+ }
90
+ }
91
+
92
+ /**
93
+ * save new data
94
+ * @param data data
95
+ * @returns data
96
+ */
97
+ async createData(data: T, issuer: string): Promise<T> {
98
+ data.__created = new Date();
99
+ data.__lastModified = new Date();
100
+ data.__createdBy = issuer;
101
+ data.__lastModifiedBy = issuer;
102
+
103
+ const dataModel = new this.dataModel(data);
104
+ const newData: T = await dataModel.save().then((res): T => {
105
+ if (res) {
106
+ return res?.toObject() as T;
107
+
108
+ } else {
109
+ throw new DyFM_Error({
110
+ ...this._getDefaultErrorSettings(
111
+ 'createData',
112
+ new Error(
113
+ `createData failed, save "${this.dataParams.dataName}" result not found! (NTS DB)`
114
+ ),
115
+ issuer
116
+ ),
117
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CD1`,
118
+ additionalContent: { data },
119
+ issuer,
120
+ });
121
+ }
122
+ }).catch((error): void => {
123
+ if (error?.flag?.includes('DYNAMO')) {
124
+ throw error;
125
+
126
+ } else {
127
+ throw new DyFM_Error({
128
+ ...this._getDefaultErrorSettings('createData', error, issuer),
129
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CD0`,
130
+ additionalContent: {
131
+ data: data,
132
+ dataModel: this.dataModel,
133
+ },
134
+ message:
135
+ `createData failed, Create new "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
136
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
137
+ issuer,
138
+ });
139
+ }
140
+ });
141
+
142
+ return this.stringifyDataId(newData, 'createData');
143
+ }
144
+
145
+ /**
146
+ * Find data by _id and update
147
+ * @param data data
148
+ * @returns data
149
+ */
150
+ async modifyData(data: T, issuer: string, dontUpdateModified?: boolean): Promise<T> {
151
+ if (this.dataParams.forbidModify) {
152
+ await this.modifyThrowMethod(data, issuer);
153
+ }
154
+
155
+ if (!dontUpdateModified) {
156
+ data.__lastModified = new Date();
157
+ data.__lastModifiedBy = issuer;
158
+ }
159
+
160
+ /**
161
+ * EZ A SZAR TELJESEN SZAR, nem friss, nem a db-be mentett adatokat ad vissza,
162
+ * átír random value-kat össze vissza, WTF
163
+ * */
164
+ /* let newData: T = */
165
+ await this.dataModel.findByIdAndUpdate(data._id, data)/* .then((res) => {
166
+ if (res) {
167
+ //return res?.toObject() as T;
168
+ } else {
169
+ throw new DyFM_Error({
170
+ ...this._getDefaultErrorSettings(
171
+ 'modifyData',
172
+ new Error(`modifyData failed, modify "${this.dataParams.dataName}" result not found! (NTS DB)`),
173
+ issuer,
174
+ ),
175
+
176
+ status: 204,
177
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FU1`,
178
+ additionalContent: { data },
179
+ issuer,
180
+ });
181
+ }
182
+ }) */.catch((error): void => {
183
+ throw new DyFM_Error({
184
+ ...this._getDefaultErrorSettings('modifyData', error, issuer),
185
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FU0`,
186
+ additionalContent: { data },
187
+ message:
188
+ `modifyData "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
189
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
190
+ issuer,
191
+ });
192
+ });
193
+
194
+ return this.stringifyDataId(data, 'modifyData');
195
+ }
196
+
197
+ // TODO: Missing issuer
198
+ /**
199
+ * returns data by _id,
200
+ * @param id id
201
+ * @returns data
202
+ */
203
+ async getDataById(id: string): Promise<T> {
204
+ if (!id) {
205
+ throw new DyFM_Error({
206
+ ...this._getDefaultErrorSettings('getDataById', new Error(`No ID provided! (NTS DB)`)),
207
+
208
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GI1`,
209
+ message: `get "${this.dataParams.dataName}" by ID was unsuccessful (NTS DB)`,
210
+ });
211
+ }
212
+
213
+ const data: T = await this.dataModel
214
+ .findById(id)
215
+ .then((res): T => res?.toObject() as T ?? null)
216
+ .catch((error): void => {
217
+ throw new DyFM_Error({
218
+ ...this._getDefaultErrorSettings('getDataById', error),
219
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GI0`,
220
+ additionalContent: { id },
221
+ message:
222
+ `get "${this.dataParams.dataName}" by ID was unsuccessful (NTS DB)` +
223
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
224
+ });
225
+ });
226
+
227
+ return this.stringifyDataId(data, 'getDataById');
228
+ }
229
+
230
+ // TODO: Missing issuer
231
+ /**
232
+ * get data by dependency data id,
233
+ * !!!: throws error if not found (errorCode on not found: NTS-DBS-GD2)
234
+ *
235
+ * @param dependencyIdsFilter id
236
+ * @returns data
237
+ */
238
+ async getDataByDependencyId(dependencyIdsFilter: { [key: string]: string }): Promise<T> {
239
+ if (!this.depKeys.length) {
240
+ throw new DyFM_Error({
241
+ ...this._getDefaultErrorSettings(
242
+ 'getDataByDependencyId',
243
+ new Error(
244
+ `dependencyDataIdKey not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
245
+ )
246
+ ),
247
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GD0`,
248
+ });
249
+ }
250
+
251
+ const data: T = await this.dataModel
252
+ .findOne(dependencyIdsFilter)
253
+ .then((res): T => res?.toObject() as T ?? null)
254
+ .catch((error): void => {
255
+ throw new DyFM_Error({
256
+ ...this._getDefaultErrorSettings('getDataByDependencyId', error),
257
+
258
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GD1`,
259
+ additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
260
+ message:
261
+ `get "${this.dataParams.dataName}" by ` +
262
+ `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
263
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
264
+ });
265
+ });
266
+
267
+ return this.stringifyDataId(data, 'getDataByDependencyId');
268
+ }
269
+
270
+ // TODO: Missing issuer
271
+ async getDataListByIds(ids: string[], findDeleted?: boolean): Promise<T[]> {
272
+ const dataList: T[] = await this.dataModel
273
+ .find({ _id: { $in: ids } })
274
+ .then((res): T[] => res as T[] ?? [])
275
+ .catch((error): void => {
276
+ throw new DyFM_Error({
277
+ ...this._getDefaultErrorSettings('getDataListByIds', error),
278
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GDL0`,
279
+ additionalContent: { ids },
280
+ message:
281
+ `get "${this.dataParams.dataName}" by IDs was unsuccessful (NTS DB)` +
282
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
283
+ });
284
+ });
285
+
286
+ if (!findDeleted) {
287
+ return dataList.filter(
288
+ (data: T): boolean => !data._deleted
289
+ ).map(
290
+ (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
291
+ );
292
+ } else {
293
+ return dataList.map(
294
+ (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
295
+ );
296
+ }
297
+ }
298
+
299
+ // TODO: Missing issuer
300
+ /**
301
+ * get data by dependency data id,
302
+ * !!!: throws error if not found (errorCode on not found: NTS-DBS-GLD2)
303
+ *
304
+ * @param dependencyIdsFilter id
305
+ * @returns dataList
306
+ */
307
+ async getDataListByDependencyId(dependencyIdsFilter: { [key: string]: string }, findDeleted?: boolean): Promise<T[]> {
308
+ if (!this.depKeys.length) {
309
+ throw new DyFM_Error({
310
+ ...this._getDefaultErrorSettings(
311
+ 'getDataListByDependencyId',
312
+ new Error(
313
+ `isDependencyHook not setted up for this dataModel (${this.dataParams.dataName}) (NTS DB)`
314
+ )
315
+ ),
316
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLD0`,
317
+ additionalContent: {
318
+ dataModel: this.dataModel,
319
+ },
320
+ });
321
+ }
322
+
323
+ const dataList: T[] = await this.dataModel
324
+ .find(dependencyIdsFilter)
325
+ .then((res): T[] => res as T[] ?? [])
326
+ .catch((error): void => {
327
+ throw new DyFM_Error({
328
+ ...this._getDefaultErrorSettings('getDataListByDependencyId', error),
329
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLD1`,
330
+ additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
331
+ message:
332
+ `get "${this.dataParams.dataName}" by ` +
333
+ `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
334
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
335
+ });
336
+ });
337
+
338
+ if (!findDeleted) {
339
+ return dataList.filter(
340
+ (data: T): boolean => !data._deleted
341
+ ).map(
342
+ (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
343
+ );
344
+ } else {
345
+ return dataList.map(
346
+ (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyId')
347
+ );
348
+ }
349
+ }
350
+
351
+ // TODO: Missing issuer
352
+ /**
353
+ * get multiple data objects by a list of DependencyIDs,
354
+ * !!!: throws error if not found (errorCode on not found: NTS-DBS-GLDS2)
355
+ *
356
+ * @param ids ids
357
+ * @returns dataList
358
+ */
359
+ async getDataListByDependencyIds(dependencyKey: string, dependencyIds: string[], findDeleted?: boolean): Promise<T[]> {
360
+ if (!this.depKeys.length) {
361
+ throw new DyFM_Error({
362
+ ...this._getDefaultErrorSettings(
363
+ 'getDataListByDependencyIds',
364
+ new Error(
365
+ `getDataListByDependencyIds not setted up for this db-service ` +
366
+ `(${this.dataParams.dataName}) (NTS DB)`
367
+ )
368
+ ),
369
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLDS0`,
370
+ });
371
+ }
372
+
373
+ if (!dependencyIds?.length) {
374
+ return [];
375
+ }
376
+
377
+ if (!dependencyKey) {
378
+ throw new DyFM_Error({
379
+ ...this._getDefaultErrorSettings(
380
+ 'getDataListByDependencyIds',
381
+ new Error(`dependencyKey is missing! (${this.dataParams.dataName}) (NTS DB)`),
382
+ ),
383
+ });
384
+ }
385
+
386
+ if (!this.depKeys.includes(dependencyKey)) {
387
+ throw new DyFM_Error({
388
+ ...this._getDefaultErrorSettings(
389
+ 'getDataListByDependencyIds',
390
+ new Error(`dependencyKey is not valid! (${dependencyKey}) (NTS DB)`),
391
+ ),
392
+ });
393
+ }
394
+
395
+ const dataList: T[] = await this.dataModel
396
+ .find({
397
+ [dependencyKey]: { $in: dependencyIds },
398
+ })
399
+ .then((res): T[] => res as T[] ?? [])
400
+ .catch((error): void => {
401
+ throw new DyFM_Error({
402
+ ...this._getDefaultErrorSettings('getDataListByDependencyIds', error),
403
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GLDS1`,
404
+ additionalContent: { dependencyIds },
405
+ message:
406
+ `get "${this.dataParams.dataName}" by "${dependencyKey}" was unsuccessful (NTS DB)` +
407
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
408
+ });
409
+ });
410
+
411
+ if (!findDeleted) {
412
+ return dataList.filter(
413
+ (data: T): boolean => !data._deleted
414
+ ).map(
415
+ (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyIds')
416
+ );
417
+ } else {
418
+ return dataList.map(
419
+ (data: T): T => this.stringifyDataId(data, 'getDataListByDependencyIds')
420
+ );
421
+ }
422
+ }
423
+
424
+ // TODO: Missing issuer
425
+ /**
426
+ * returns all data from database,
427
+ * !!!: throws error if not found (errorCode on not found: NTS-DBS-GA1)
428
+ *
429
+ * @returns dataList
430
+ */
431
+ async getAll(findDeleted?: boolean): Promise<T[]> {
432
+ const dataList: T[] = await this.dataModel
433
+ .find()
434
+ .then((res): T[] => res as T[] ?? [])
435
+ .catch((error): void => {
436
+ throw new DyFM_Error({
437
+ ...this._getDefaultErrorSettings('getAll', error),
438
+
439
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GA0`,
440
+ message:
441
+ `get all "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
442
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
443
+ });
444
+ });
445
+
446
+ if (!findDeleted) {
447
+ return dataList.filter(
448
+ (data: T): boolean => !data._deleted
449
+ ).map(
450
+ (data: T): T => this.stringifyDataId(data, 'getAll')
451
+ );
452
+ } else {
453
+ return dataList.map(
454
+ (data: T): T => this.stringifyDataId(data, 'getAll')
455
+ );
456
+ }
457
+ }
458
+
459
+ async markDeletedById(id: string, issuer: string): Promise<void> {
460
+ if (this.dataParams.forbidDelete) {
461
+ await this.deleteThrowMethod(id, issuer);
462
+ }
463
+
464
+ await this.dataModel.findByIdAndUpdate(
465
+ id,
466
+ {
467
+ _deleted: new Date(),
468
+ _deletedBy: issuer,
469
+ },
470
+ /* issuer */
471
+ ).catch(
472
+ (error): void => {
473
+ throw new DyFM_Error({
474
+ ...this._getDefaultErrorSettings('markDeletedById', error, issuer),
475
+
476
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-MD0`,
477
+ additionalContent: { id },
478
+ message:
479
+ `mark deleted "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
480
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
481
+ issuer,
482
+ });
483
+ }
484
+ );
485
+ }
486
+
487
+ async markDeletedByDependencyId(dependencyIdsFilter: { [key: string]: string }, issuer: string): Promise<void> {
488
+ if (this.dataParams.forbidDelete) {
489
+ await this.deleteThrowMethod(dependencyIdsFilter, issuer);
490
+ }
491
+
492
+ await this.dataModel.updateMany(
493
+ dependencyIdsFilter,
494
+ {
495
+ _deleted: new Date(),
496
+ _deletedBy: issuer,
497
+ }
498
+ ).catch((error): void => {
499
+ throw new DyFM_Error({
500
+ ...this._getDefaultErrorSettings('markDeletedByDependencyId', error, issuer),
501
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-MDD0`,
502
+ additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
503
+ message:
504
+ `markDeleted "${this.dataParams.dataName}" by ` +
505
+ `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
506
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
507
+ issuer,
508
+ });
509
+ });
510
+ }
511
+
512
+ async restoreDeletedById(id: string, issuer: string): Promise<void> {
513
+ await this.dataModel.findByIdAndUpdate(
514
+ id,
515
+ {
516
+ _deleted: null,
517
+ __lastModified: new Date(),
518
+ __lastModifiedBy: issuer,
519
+ },
520
+ /* issuer */
521
+ ).catch((error): void => {
522
+ throw new DyFM_Error({
523
+ ...this._getDefaultErrorSettings('restoreDeletedById', error, issuer),
524
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-RD0`,
525
+ additionalContent: { id },
526
+ message:
527
+ `restoreDeleted "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
528
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
529
+ issuer,
530
+ });
531
+ });
532
+ }
533
+
534
+ async restoreDeletedByDependencyId(
535
+ dependencyIdsFilter: { [key: string]: string },
536
+ issuer: string
537
+ ): Promise<void> {
538
+ await this.dataModel.updateMany(
539
+ dependencyIdsFilter,
540
+ {
541
+ _deleted: null,
542
+ __lastModified: new Date(),
543
+ __lastModifiedBy: issuer,
544
+ }
545
+ ).catch((error): void => {
546
+ throw new DyFM_Error({
547
+ ...this._getDefaultErrorSettings('restoreDeletedByDependencyId', error, issuer),
548
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-RDD0`,
549
+ additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
550
+ message:
551
+ `restoreDeleted "${this.dataParams.dataName}" by ` +
552
+ `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
553
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
554
+ issuer,
555
+ });
556
+ });
557
+ }
558
+
559
+ // TODO: Missing issuer
560
+ async getDeletedDataList(): Promise<T[]> {
561
+ const dataList: T[] = await this.dataModel
562
+ .getAll()
563
+ .then((res): T[] => res as T[] ?? [])
564
+ .catch((error): void => {
565
+ throw new DyFM_Error({
566
+ ...this._getDefaultErrorSettings('getDeletedData', error),
567
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GDD0`,
568
+ message:
569
+ `get deleted "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
570
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
571
+ });
572
+ });
573
+
574
+ return dataList.filter(
575
+ (data: T): boolean => Boolean(data._deleted)
576
+ ).map((data: T): T => this.stringifyDataId(data, 'getDeletedData'));
577
+ }
578
+
579
+ // TODO: Missing issuer
580
+ /**
581
+ * deleted data by id
582
+ * @param id id
583
+ */
584
+ async trueDeleteDataById(id: string): Promise<void> {
585
+ if (this.dataParams.forbidDelete) {
586
+ await this.deleteThrowMethod(id/* , issuer */);
587
+ }
588
+
589
+ await this.dataModel
590
+ .findByIdAndDelete(id)
591
+ .catch((error): void => {
592
+ throw new DyFM_Error({
593
+ ...this._getDefaultErrorSettings('deleteDataById', error),
594
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DD0`,
595
+ additionalContent: { id },
596
+ message:
597
+ `delete "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
598
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
599
+ });
600
+ });
601
+ }
602
+ readonly deleteDataById = this.trueDeleteDataById;
603
+
604
+ // TODO: Missing issuer
605
+ /**
606
+ * deleted data by id
607
+ * @param dependencyId id
608
+ */
609
+ async trueDeleteDataByDependencyId(dependencyIdsFilter: { [key: string]: string }): Promise<void> {
610
+ if (this.dataParams.forbidDelete) {
611
+ await this.deleteThrowMethod(dependencyIdsFilter/* , issuer */);
612
+ }
613
+
614
+ if (!this.depKeys.length) {
615
+ throw new DyFM_Error({
616
+ ...this._getDefaultErrorSettings(
617
+ 'deleteDataByDependencyId',
618
+ new Error(
619
+ `dependencyDataIdKey not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
620
+ )
621
+ ),
622
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DDD0`,
623
+ });
624
+ }
625
+
626
+ await this.dataModel
627
+ .deleteMany(dependencyIdsFilter)
628
+ .catch((error): void => {
629
+ throw new DyFM_Error({
630
+ ...this._getDefaultErrorSettings('deleteDataByDependencyId', error),
631
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DDD1`,
632
+ additionalContent: { dependencyIdsFilter: dependencyIdsFilter },
633
+ message:
634
+ `delete "${this.dataParams.dataName}" by ` +
635
+ `"${Object.keys(dependencyIdsFilter).join(', ')}" was unsuccessful (NTS DB)` +
636
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
637
+ });
638
+ });
639
+ }
640
+ readonly deleteDataByDependencyId = this.trueDeleteDataByDependencyId;
641
+
642
+ // TODO: Missing issuer
643
+ async trueDeleteAllData(): Promise<void> {
644
+ if (this.dataParams.forbidDelete) {
645
+ await this.deleteThrowMethod(null/* , issuer */);
646
+ }
647
+
648
+ await this.dataModel.deleteMany().catch((error): void => {
649
+ throw new DyFM_Error({
650
+ ...this._getDefaultErrorSettings('deleteAllData', error),
651
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-DAD0`,
652
+ message:
653
+ `delete all "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
654
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
655
+ });
656
+ });
657
+ }
658
+ readonly deleteAllData = this.trueDeleteAllData;
659
+
660
+ // TODO: Missing issuer
661
+ /**
662
+ * returns search result for searchBy object params
663
+ * can use lists or xRange values for searchBy obj properties
664
+ *
665
+ * @param filterBy filter
666
+ * @param narrowByDependencyIds id
667
+ * @returns dataList
668
+ */
669
+ async searchData(
670
+ filterBy: DyFM_DBFilter<T>,
671
+ narrowByDependencyIds?: string[],
672
+ narrowByDependencyKey?: string,
673
+ findDeleted?: boolean
674
+ ): Promise<T[]> {
675
+ const filter = {};
676
+
677
+ if (0 < narrowByDependencyIds.length) {
678
+ if (!this.depKeys.length) {
679
+ throw new DyFM_Error({
680
+ ...this._getDefaultErrorSettings(
681
+ 'searchData',
682
+ new Error(
683
+ `dependencyDataIdKey not setted up for this db-service (${this.dataParams.dataName}) (NTS DB)`
684
+ )
685
+ ),
686
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-SD0`,
687
+ });
688
+ }
689
+
690
+ if (!narrowByDependencyKey) {
691
+ if (this.depKeys.length === 1) {
692
+ narrowByDependencyKey = this.depKeys[0];
693
+ } else {
694
+ throw new DyFM_Error({
695
+ ...this._getDefaultErrorSettings(
696
+ 'searchData',
697
+ new Error(`dependencyKey is missing! (${this.dataParams.dataName}) (NTS DB)`),
698
+ ),
699
+ });
700
+ }
701
+ }
702
+
703
+ filter[narrowByDependencyKey] = { $in: narrowByDependencyIds };
704
+ }
705
+
706
+ Object.values(this.dataParams.properties).forEach(
707
+ (modelParam: DyFM_DataProperty_Params<any, T>): void => {
708
+ if (
709
+ (filterBy[modelParam.key] !== null && filterBy[modelParam.key] !== undefined) ||
710
+ filterBy[modelParam.key + 'Range']
711
+ ) {
712
+ if (modelParam.key.includes('Range') || modelParam.type.includes('[]')) {
713
+ // inverz search filter (for Range and Array functions)
714
+ if (modelParam.key.includes('Range')) {
715
+ const searchParamKeyWithoutRange = modelParam.key.split('Range')[0];
716
+
717
+ if (
718
+ filterBy[searchParamKeyWithoutRange] !== null &&
719
+ filterBy[searchParamKeyWithoutRange] !== undefined
720
+ ) {
721
+ filter[modelParam.key] = {
722
+ from: { $lte: filterBy[searchParamKeyWithoutRange] },
723
+ to: { $gte: filterBy[searchParamKeyWithoutRange] },
724
+ };
725
+ }
726
+ } else {
727
+ if (
728
+ filterBy[modelParam.key] !== null &&
729
+ filterBy[modelParam.key] !== undefined
730
+ ) {
731
+ filter[modelParam.key] = { $in: filterBy[modelParam.key] };
732
+ }
733
+ }
734
+ } else {
735
+ // basic search filter
736
+ if (filterBy[modelParam.key + 'Range']) {
737
+ if (
738
+ filterBy[modelParam.key + 'Range'].from ||
739
+ filterBy[modelParam.key + 'Range'].to
740
+ ) {
741
+ filter[modelParam.key] = {};
742
+
743
+ if (filterBy[modelParam.key + 'Range'].from) {
744
+ filter[modelParam.key].$gte = filterBy[modelParam.key + 'Range'].from;
745
+ }
746
+
747
+ if (filterBy[modelParam.key + 'Range'].to) {
748
+ filter[modelParam.key].$lte = filterBy[modelParam.key + 'Range'].to;
749
+ }
750
+ }
751
+ } else if (
752
+ filterBy[modelParam.key] !== null &&
753
+ filterBy[modelParam.key] !== undefined
754
+ ) {
755
+ if (filterBy[modelParam.key].lenght > 0) {
756
+ filter[modelParam.key] = { $in: filterBy[modelParam.key] };
757
+ }
758
+ }
759
+ }
760
+ }
761
+ }
762
+ );
763
+
764
+ let dataList: T[] = await this.dataModel
765
+ .find(filter)
766
+ .then((res): T[] => res as T[] ?? [])
767
+ .catch((error): void => {
768
+ throw new DyFM_Error({
769
+ ...this._getDefaultErrorSettings('searchData', error),
770
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-SD1`,
771
+ additionalContent: { filterBy, narrowByDependencyIds },
772
+ message:
773
+ `search "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
774
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
775
+ });
776
+ });
777
+
778
+ if (!findDeleted && (filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined) {
779
+ dataList = dataList.filter((data: T): boolean => !data._deleted);
780
+ }
781
+
782
+ return dataList.map((data: T): T => this.stringifyDataId(data, 'searchData'));
783
+ }
784
+
785
+ // ----------------------------------------------------------------------------------
786
+ // ----------------------------------------------------------------------------------
787
+ // ----------------------------------------------------------------------------------
788
+ // DIRECT Basic MONGOOSE FUNCTIONS (with error handlings)
789
+
790
+ /**
791
+ * Find the data first by any of its parameters,
792
+ * !!!: throws error if not found (errorCode on not found: NTS-DBS-FO1)
793
+ *
794
+ * @param filterBy if you can, use unique parameters for find!
795
+ *
796
+ * @example
797
+ * // by email:
798
+ * { email: email }
799
+ * //
800
+ * @example
801
+ * // or by id that is in list:
802
+ * { userIds: { $in: this.userId } }
803
+ * // or by userIds:
804
+ * { userId: { $in: userIds } }
805
+ * //
806
+ * @example
807
+ * // or by number or Date that is Greater Than AND Less Than:
808
+ * { points: { $gt: 2, $lt: 14 } }
809
+ * // further tools (syntax matches with $gt):
810
+ * $eq: // Matches values that are EQual to a specified value.
811
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
812
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
813
+ * $ne: // Matches all values that are Not Equal to a specified value.
814
+ * $nin: // Matches None of the values specified IN an array.
815
+ * //
816
+ * @returns {T} data: T
817
+ */
818
+ async findOne(filterBy: DyFM_DBFilter<T>): Promise<T> {
819
+ const data: T = await this.dataModel
820
+ .findOne(filterBy)
821
+ .then((res): T => res as T ?? null)
822
+ .catch((error): void => {
823
+ throw new DyFM_Error({
824
+ ...this._getDefaultErrorSettings('findOne', error),
825
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FO0`,
826
+ additionalContent: { filterBy },
827
+ message:
828
+ `findOne "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
829
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
830
+ });
831
+ });
832
+
833
+ return this.stringifyDataId(data, 'findOne');
834
+ }
835
+
836
+ /**
837
+ * #MONGOOSE FUNCTION
838
+ * Find the data first by any of its parameters,
839
+ * !!!: throws error if not found (errorCode on not found: NTS-DBS-F1)
840
+ *
841
+ * @param filterBy if you can, use unique parameters for find!
842
+ *
843
+ * @example
844
+ * // by email:
845
+ * { email: email }
846
+ * //
847
+ * @example
848
+ * // or by id that is in list:
849
+ * { userIds: { $in: this.userId } }
850
+ * // or by userIds:
851
+ * { userId: { $in: userIds } }
852
+ * //
853
+ * @example
854
+ * // or by number or Date that is Greater Than AND Less Than:
855
+ * { points: { $gt: 2, $lt: 14 } }
856
+ * // further tools (syntax matches with $gt):
857
+ * $eq: // Matches values that are EQual to a specified value.
858
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
859
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
860
+ * $ne: // Matches all values that are Not Equal to a specified value.
861
+ * $nin: // Matches None of the values specified IN an array.
862
+ * //
863
+ * @param options BFR-008: opcionalis projection/limit/sort — DB-szinten szukit (a nagy mezok be sem toltodnek)
864
+ * @returns {T[]} dataList: T[]
865
+ */
866
+ async find(filterBy: DyFM_DBFilter<T>, findDeleted?: boolean, options?: DyNTS_DBQueryOptions<T>): Promise<T[]> {
867
+ // BFR-OVERSEER-008 — options megadasakor a soft-delete szures QUERY-szintre kerul: limit mellett a
868
+ // memoriabeli post-filter hibas darabszamot adna, projekcio mellett (kihagyott `_deleted` mezovel)
869
+ // hibasan atengedne a torolt dokumentumokat. A `_deleted` soft-delete-kor `new Date()`, egyebkent
870
+ // HIANYZIK → a Mongo `_deleted: null` (missing VAGY null) a post-filter `!data._deleted` ekvivalense.
871
+ const deletedGuardInQuery: boolean =
872
+ !!options && !findDeleted && (filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined;
873
+ const effectiveFilter: DyFM_DBFilter<T> = deletedGuardInQuery
874
+ ? { ...(filterBy as DyFM_DBFilterSimple<T>), _deleted: null } as unknown as DyFM_DBFilter<T>
875
+ : filterBy;
876
+
877
+ // A szukites (select/sort/limit) DB-szinten tortenik → a nagy mezok be sem toltodnek a heap-be.
878
+ let query = this.dataModel.find(effectiveFilter);
879
+ if (options?.projection) { query = query.select(options.projection); }
880
+ if (options?.sort) { query = query.sort(options.sort); }
881
+ if (options?.limit) { query = query.limit(options.limit); }
882
+
883
+ let dataList: T[] = await query
884
+ .then((res): T[] => res as T[] ?? [])
885
+ .catch((error): void => {
886
+ throw new DyFM_Error({
887
+ ...this._getDefaultErrorSettings('find', error),
888
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-F0`,
889
+ additionalContent: { filterBy },
890
+ message:
891
+ `find "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
892
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
893
+ });
894
+ });
895
+
896
+ if (!findDeleted && !deletedGuardInQuery && (filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined) {
897
+ dataList = dataList.filter((data: T): boolean => !data._deleted);
898
+ }
899
+
900
+ return dataList.map((data: T): T => this.stringifyDataId(data, 'find'));
901
+ }
902
+
903
+ /**
904
+ * #MONGOOSE FUNCTION
905
+ * Find the data first by any of its parameters
906
+ * WARNING: This function will not gives you back the total number of data in the database!
907
+ *
908
+ * @param filterBy if you can, use unique parameters for find!
909
+ *
910
+ * @example
911
+ * // by email:
912
+ * { email: email }
913
+ * //
914
+ * @example
915
+ * // or by id that is in list:
916
+ * { userIds: { $in: this.userId } }
917
+ * // or by userIds:
918
+ * { userId: { $in: userIds } }
919
+ * //
920
+ * @example
921
+ * // or by number or Date that is Greater Than AND Less Than:
922
+ * { points: { $gt: 2, $lt: 14 } }
923
+ * // further tools (syntax matches with $gt):
924
+ * $eq: // Matches values that are EQual to a specified value.
925
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
926
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
927
+ * $ne: // Matches all values that are Not Equal to a specified value.
928
+ * $nin: // Matches None of the values specified IN an array.
929
+ * //
930
+ * @param page page
931
+ * @param pageSize pageSize
932
+ * @param sort
933
+ * @example
934
+ * // by dateTime (this uses the basic sort function):
935
+ * { dateTime: -1 }
936
+ * //
937
+ * @returns {T[]} dataList: T[]
938
+ */
939
+ async findWithPaging(
940
+ filterBy: DyFM_DBFilter<T>,
941
+ page: number,
942
+ pageSize: number,
943
+ sort?: DyFM_DBSort<T>
944
+ ): Promise<T[]> {
945
+ /* if (filterBy['_deleted'] === undefined) {
946
+ filterBy['_deleted'] = null;
947
+ } */
948
+
949
+ const dataList: T[] = await this.dataModel
950
+ .find(filterBy)
951
+ .sort(sort)
952
+ .skip(page * pageSize)
953
+ .limit(pageSize)
954
+ .then((res): T => res ?? [])
955
+ .catch((error): void => {
956
+ throw new DyFM_Error({
957
+ ...this._getDefaultErrorSettings('findWithPaging', error),
958
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-WP0`,
959
+ additionalContent: { filterBy, page, pageSize, sort },
960
+ message:
961
+ `findWithPaging "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
962
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
963
+ });
964
+ });
965
+
966
+ /* if ((filterBy as DyFM_DBFilterSimple<T>)._deleted === undefined) {
967
+ dataList = dataList.filter((data: T): boolean => !data._deleted);
968
+ } */
969
+
970
+ return dataList.map((data: T): T => this.stringifyDataId(data, 'find'));
971
+ }
972
+
973
+ /**
974
+ * #MONGOOSE FUNCTION
975
+ * Find data by _id and update
976
+ *
977
+ * @param id id
978
+ * @param update update
979
+ * @returns data
980
+ */
981
+ async findByIdAndUpdate(
982
+ id: string,
983
+ update: DyNTS_DBUpdate<T>,
984
+ issuer: string,
985
+ dontUpdateModified?: boolean
986
+ ): Promise<T> {
987
+ if (this.dataParams.forbidModify) {
988
+ await this.modifyThrowMethod(update, issuer);
989
+ }
990
+
991
+ if (!dontUpdateModified) {
992
+ update.__lastModified = new Date();
993
+ update.__lastModifiedBy = issuer;
994
+ }
995
+
996
+ const data: T = await this.dataModel
997
+ .findByIdAndUpdate(id, update)
998
+ .then((res): T => res?.toObject() as T ?? null)
999
+ .catch((error): void => {
1000
+ throw new DyFM_Error({
1001
+ ...this._getDefaultErrorSettings('findByIdAndUpdate', error, issuer),
1002
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FIU0`,
1003
+ additionalContent: { id, update },
1004
+ message:
1005
+ `findByIdAndUpdate "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1006
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1007
+ issuer,
1008
+ });
1009
+ });
1010
+
1011
+ return this.stringifyDataId(data, 'findByIdAndUpdate');
1012
+ }
1013
+
1014
+ /**
1015
+ * #MONGOOSE FUNCTION
1016
+ * Atomi compare-and-set: filter-alapú find + update EGY műveletben, a MÓDOSÍTOTT dokumentum
1017
+ * visszaadásával (BFR-FDPTOKENSERVICE-006).
1018
+ *
1019
+ * A `findByIdAndUpdate` (id-only, nem filterezhető) és az `updateOne` (filterezhető, de void —
1020
+ * nem különíthető el a winner/loser konkurens state-átmenetnél) egyike sem elég CAS-hoz: egy
1021
+ * state-machine `transitionStatus`-jellegű átmenetnél a filter a FELTÉTEL (pl. `{_id, status:
1022
+ * 'locked'}`), és a visszatérő érték dönti el, hogy EZ a hívás nyerte-e az átmenetet.
1023
+ * `null` = nincs match (a feltétel már nem áll — a versenytárs nyert / state-collision).
1024
+ *
1025
+ * A `__lastModified`/`forbidModify` szemantika a `findByIdAndUpdate`-tel EGYEZŐ (egységes
1026
+ * update-viselkedés a base-ben); a `{ new: true }` a MÓDOSÍTOTT dokumentumot adja vissza.
1027
+ */
1028
+ async findOneAndUpdate(
1029
+ filterBy: DyFM_DBFilter<T>,
1030
+ update: DyNTS_DBUpdate<T>,
1031
+ issuer: string,
1032
+ dontUpdateModified?: boolean
1033
+ ): Promise<T | null> {
1034
+ if (this.dataParams.forbidModify) {
1035
+ await this.modifyThrowMethod(update, issuer);
1036
+ }
1037
+
1038
+ if (!dontUpdateModified) {
1039
+ update.__lastModified = new Date();
1040
+ update.__lastModifiedBy = issuer;
1041
+ }
1042
+
1043
+ const data: T | null = await this.dataModel
1044
+ .findOneAndUpdate(filterBy, update, { new: true })
1045
+ .then((res): T | null => res?.toObject() as T ?? null)
1046
+ .catch((error): never => {
1047
+ throw new DyFM_Error({
1048
+ ...this._getDefaultErrorSettings('findOneAndUpdate', error, issuer),
1049
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-FOU0`,
1050
+ additionalContent: { filterBy, update },
1051
+ message:
1052
+ `findOneAndUpdate "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1053
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1054
+ issuer,
1055
+ });
1056
+ });
1057
+
1058
+ // no-match (CAS lost / feltétel nem áll): a null ÉRVÉNYES eredmény, nem hiba
1059
+ if (!data) {
1060
+ return null;
1061
+ }
1062
+
1063
+ return this.stringifyDataId(data, 'findOneAndUpdate');
1064
+ }
1065
+
1066
+ /**
1067
+ * #MONGOOSE FUNCTION
1068
+ * Find the data first by any of its parameters
1069
+ *
1070
+ * @param filter This uses the basic Mongoose updateOne.
1071
+ * If you can, use unique parameters for find!
1072
+ * @example
1073
+ * // by email:
1074
+ * { email: email }
1075
+ * //
1076
+ * @example
1077
+ * // or by id that is in list:
1078
+ * { userIds: { $in: this.userId } }
1079
+ * // or by userIds:
1080
+ * { userId: { $in: userIds } }
1081
+ * //
1082
+ * @example
1083
+ * // or by number or Date that is Greater Than AND Less Than:
1084
+ * { points: { $gt: 2, $lt: 14 } }
1085
+ * // further tools (syntax matches with $gt):
1086
+ * $eq: // Matches values that are EQual to a specified value.
1087
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
1088
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
1089
+ * $ne: // Matches all values that are Not Equal to a specified value.
1090
+ * $nin: // Matches None of the values specified IN an array.
1091
+ * //
1092
+ *
1093
+ * @param update this uses the basic Mongoose updateOne
1094
+ * @example
1095
+ * // increase a specific value (here by 15):
1096
+ * { $inc: { popularity: 15 } }
1097
+ * //
1098
+ * @example
1099
+ * // or add element to a list:
1100
+ * { $push: { reactions: this.newReaction }
1101
+ * // or add multiple elements to a list
1102
+ * { $push: { schedule: {$each: [ monday, tuesday, wednesday ] } } }
1103
+ * //
1104
+ * @example
1105
+ * // or all at once
1106
+ * {
1107
+ * $inc: { popularity: this.newVote.amount },
1108
+ * emailVerified: true,
1109
+ * $push: { reactions: this.newReaction }
1110
+ * }
1111
+ * // further tools (syntax matches with $inc):
1112
+ * $currentDate: // Sets the value of a field to current date, either as a Date or a Timestamp.
1113
+ * $min: // Only updates the field if the specified value is less than the existing field value.
1114
+ * $max: // Only updates the field if the specified value is greater than the existing field value.
1115
+ * $mul: // Multiplies the value of the field by the specified amount.
1116
+ * $rename: // Renames a field.
1117
+ * $unset: // Removes the specified field from a document. (set: "" to value)
1118
+ * //
1119
+ */
1120
+ async updateOne(
1121
+ filterBy: DyFM_DBFilter<T>,
1122
+ update: DyNTS_DBUpdate<T>,
1123
+ issuer: string,
1124
+ dontUpdateModified?: boolean
1125
+ ): Promise<void> {
1126
+ if (this.dataParams.forbidModify) {
1127
+ await this.modifyThrowMethod(update, issuer);
1128
+ }
1129
+
1130
+ if (!dontUpdateModified) {
1131
+ update.__lastModified = new Date();
1132
+ update.__lastModifiedBy = issuer;
1133
+ }
1134
+
1135
+ await this.dataModel
1136
+ .updateOne(filterBy, update)
1137
+ .catch((error): void => {
1138
+ throw new DyFM_Error({
1139
+ ...this._getDefaultErrorSettings('updateOne', error, issuer),
1140
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-UO0`,
1141
+ additionalContent: { filterBy, update },
1142
+ message:
1143
+ `updateOne "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1144
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1145
+ issuer,
1146
+ });
1147
+ });
1148
+ }
1149
+
1150
+ /**
1151
+ * #MONGOOSE FUNCTION
1152
+ * update one parameter by a specific
1153
+ *
1154
+ * @param filter This uses the basic Mongoose updateMany.
1155
+ * @example
1156
+ * // by email:
1157
+ * { email: email }
1158
+ * //
1159
+ * @example
1160
+ * // or by id that is in list:
1161
+ * { userIds: { $in: this.userId } }
1162
+ * // or by userIds:
1163
+ * { userId: { $in: userIds } }
1164
+ * //
1165
+ * @example
1166
+ * // or by number or Date that is Greater Than AND Less Than:
1167
+ * { points: { $gt: 2, $lt: 14 } }
1168
+ * // further tools (syntax matches with $gt):
1169
+ * $eq: // Matches values that are EQual to a specified value.
1170
+ * $gte: // Matches values that are Greater Than OR Equal to a specified value.
1171
+ * $lte: // Matches values that are Less Than or Equal to a specified value.
1172
+ * $ne: // Matches all values that are Not Equal to a specified value.
1173
+ * $nin: // Matches None of the values specified IN an array.
1174
+ * //
1175
+ *
1176
+ * @param update this uses the basic Mongoose updateOne
1177
+ * @example
1178
+ * // increase a specific value (here by 15):
1179
+ * { $inc: { popularity: 15 } }
1180
+ * //
1181
+ * @example
1182
+ * // or add element to a list:
1183
+ * { $push: { reactions: this.newReaction }
1184
+ * // or add multiple elements to a list
1185
+ * { $push: { schedule: {$each: [ monday, tuesday, wednesday ] } } }
1186
+ * //
1187
+ * @example
1188
+ * // or all at once
1189
+ * {
1190
+ * $inc: { popularity: this.newVote.amount },
1191
+ * emailVerified: true,
1192
+ * $push: { reactions: this.newReaction }
1193
+ * }
1194
+ * // further tools (syntax matches with $inc):
1195
+ * $currentDate: // Sets the value of a field to current date, either as a Date or a Timestamp.
1196
+ * $min: // Only updates the field if the specified value is less than the existing field value.
1197
+ * $max: // Only updates the field if the specified value is greater than the existing field value.
1198
+ * $mul: // Multiplies the value of the field by the specified amount.
1199
+ * $rename: // Renames a field.
1200
+ * $unset: // Removes the specified field from a document. (set: "" to value)
1201
+ * //
1202
+ */
1203
+ async updateMany(
1204
+ filterBy: DyFM_DBFilter<T>,
1205
+ update: DyNTS_DBUpdate<T>,
1206
+ issuer: string,
1207
+ dontUpdateModified?: boolean
1208
+ ): Promise<void> {
1209
+ if (this.dataParams.forbidModify) {
1210
+ await this.modifyThrowMethod(update, issuer);
1211
+ }
1212
+
1213
+ if (!dontUpdateModified) {
1214
+ update.__lastModified = new Date();
1215
+ update.__lastModifiedBy = issuer;
1216
+ }
1217
+
1218
+ await this.dataModel
1219
+ .updateMany(filterBy, update)
1220
+ .catch((error): void => {
1221
+ throw new DyFM_Error({
1222
+ ...this._getDefaultErrorSettings('updateMany', error, issuer),
1223
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-UM0`,
1224
+ additionalContent: { filterBy, update },
1225
+ message:
1226
+ `updateMany "${this.dataParams.dataName}" was unsuccessful (NTS DB)` +
1227
+ `\n error: ${DyFM_Error.getErrorMessage(error)}`,
1228
+ issuer,
1229
+ });
1230
+ });
1231
+ }
1232
+
1233
+ /**
1234
+ * {
1235
+ "mappings": {
1236
+ "dynamic": true,
1237
+ "fields": {
1238
+ "embedding": {
1239
+ "type": "knnVector",
1240
+ "dimensions": 768
1241
+ }
1242
+ }
1243
+ }
1244
+ }
1245
+ */
1246
+ /**
1247
+ *
1248
+ * @param set db.collection.aggregate([
1249
+ {
1250
+ $vectorSearch: {
1251
+ index: "index_neve",
1252
+ queryVector: [a keresett embedding],
1253
+ path: "title.embedding",
1254
+ numCandidates: 100,
1255
+ limit: 5
1256
+ }
1257
+ },
1258
+ {
1259
+ $vectorSearch: {
1260
+ index: "index_neve",
1261
+ queryVector: [a keresett embedding],
1262
+ path: "description.embedding",
1263
+ numCandidates: 100,
1264
+ limit: 5
1265
+ }
1266
+ }
1267
+ ]);
1268
+ * @returns
1269
+ */
1270
+ async aggregate(set: any) {
1271
+ return this.dataModel.aggregate(set);
1272
+ }
1273
+
1274
+ // ----------------------------------------------------------------------------------
1275
+ // ----------------------------------------------------------------------------------
1276
+ // ----------------------------------------------------------------------------------
1277
+ // PRIVATE FUNCTIONS
1278
+
1279
+ private stringifyDataId(data: T, fnName: string): T {
1280
+ if (data?._id && (typeof data._id !== 'string' || typeof data._id === 'object')) {
1281
+ data._id = `${data._id}`;
1282
+
1283
+ if (typeof data._id !== 'string' || typeof data._id === 'object') {
1284
+ data = JSON.parse(JSON.stringify(data));
1285
+
1286
+ if (typeof data._id !== 'string' || typeof data._id === 'object') {
1287
+ DyFM_Log.error(
1288
+ `data._id stringifying failed! Please notfiy the DynamoNTS developers! (${fnName})`,
1289
+ new Error()
1290
+ );
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+ return data;
1296
+ }
1297
+
1298
+ private _getDefaultErrorSettings(
1299
+ fnName: string,
1300
+ error: DyFM_AnyError,
1301
+ issuer?: string
1302
+ ): DyFM_Error_Settings {
1303
+ return {
1304
+ status: (error as DyFM_Error)?.___status ?? 500,
1305
+ message: (error as Error)?.message ??
1306
+ (error as DyFM_Error)?._message ??
1307
+ `${fnName} was UNSUCCESSFUL (NTS-DB)`,
1308
+ addECToUserMsg: !(error as DyFM_Error)?.__userMessage,
1309
+ userMessage: (error as DyFM_Error)?.__userMessage ?? this.defaultErrorUserMsg,
1310
+ issuer: issuer,
1311
+ issuerService: this.serviceName,
1312
+ error: error,
1313
+ };
1314
+ }
1315
+
1316
+ // ----------------------------------------------------------------------------------
1317
+ // PRIVATE BUILD FUNCTIONS
1318
+
1319
+ /**
1320
+ * builds and returns mongoose schema
1321
+ * @returns schema
1322
+ */
1323
+ private getSchema(): mongoose.Schema {
1324
+ this.dataParams.properties = this.addMetadataToProperties(this.dataParams.properties);
1325
+
1326
+ if (this.dataParams.dataName.includes(DyNTS_archiveSuffix)) {
1327
+ this.dataParams.properties = this.addArchiveMetadataToProperties(this.dataParams.properties);
1328
+ }
1329
+
1330
+ const schemaSettings: any = this.buildMongooseSchemaSettingsObjByModelParams(
1331
+ this.dataParams.properties
1332
+ );
1333
+
1334
+ /* schema = this.addMetadataToSchema(schema); */
1335
+
1336
+ /* if (this.dataParams.dataName.includes(DyNTS_archiveSuffix)) {
1337
+ schema = this.addArchiveMetadataToSchema(schema);
1338
+ } */
1339
+
1340
+ if (schemaSettings['_id']) {
1341
+ delete schemaSettings['_id'];
1342
+ }
1343
+
1344
+ return new Schema(schemaSettings);
1345
+ }
1346
+
1347
+ /**
1348
+ * builds mongoose schema building settings object by dynamoDataModelParamsList
1349
+ * @param properties DynamoNTSDataPropertyParams
1350
+ * @returns mongoose schema object
1351
+ */
1352
+ private buildMongooseSchemaSettingsObjByModelParams(properties: DyFM_DataProperties<T>): any {
1353
+ const schemaSettingsObj = {};
1354
+
1355
+ /* if (!properties) {
1356
+ properties = this.dataParams.properties;
1357
+ } */
1358
+
1359
+ Object.values(properties).forEach((property: DyFM_DataProperty_Params<any, T>): void => {
1360
+ if (!property) {
1361
+ DyFM_Log.warn(`property is undefined on "${this.dataParams.dataName}" (NTS DB)`);
1362
+
1363
+ return;
1364
+ }
1365
+
1366
+ if (!property.key) {
1367
+ const missingKeys = Object.keys(properties).filter((key: string) => !properties[key].key);
1368
+
1369
+ throw new DyFM_Error({
1370
+ ...this._getDefaultErrorSettings(
1371
+ 'buildMongooseSchemaByModelParams',
1372
+ new Error(
1373
+ `property.key is undefined on "${this.dataParams.dataName}" (NTS DB) ` +
1374
+ `(keys: ${Object.keys(properties).join(', ')}) ` +
1375
+ `(missing keys: ${missingKeys.join(', ')})`
1376
+ )
1377
+ ),
1378
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-BMSBP0`,
1379
+ additionalContent: {
1380
+ property: property,
1381
+ dataParams: this.dataParams,
1382
+ missingKeys: missingKeys,
1383
+ },
1384
+ });
1385
+ }
1386
+
1387
+ if (property.forbidden) {
1388
+ return;
1389
+ }
1390
+
1391
+ const beType = this.getBEType(property.type as DyFM_BasicProperty_Type);
1392
+
1393
+ /* TODO if (beType === Array && property.archiveable && !property.archiveListAfter) {
1394
+ property.archiveListAfter = DyNTS_global_settings.archiveListAfter;
1395
+ } */
1396
+
1397
+ if (
1398
+ beType !== Object ||
1399
+ !property?.subObjectParams ||
1400
+ (property?.subObjectParams &&
1401
+ Object.keys(property.subObjectParams).length == 0)
1402
+ ) {
1403
+ schemaSettingsObj[property.key] = {
1404
+ type: beType,
1405
+ };
1406
+
1407
+ if (property.index) {
1408
+ schemaSettingsObj[property.key].index = true;
1409
+ }
1410
+
1411
+ if (property.unique) {
1412
+ schemaSettingsObj[property.key].unique = true;
1413
+ }
1414
+
1415
+ if (property.required) {
1416
+ schemaSettingsObj[property.key].required = true;
1417
+ }
1418
+
1419
+ if (property.minlength) {
1420
+ schemaSettingsObj[property.key].minlength = property.minlength;
1421
+ }
1422
+
1423
+ if (property.maxlength) {
1424
+ schemaSettingsObj[property.key].maxlength = property.maxlength;
1425
+ }
1426
+ } else {
1427
+ schemaSettingsObj[property.key] = this.buildMongooseSchemaSettingsObjByModelParams(
1428
+ property.subObjectParams
1429
+ );
1430
+ }
1431
+ });
1432
+
1433
+ return schemaSettingsObj;
1434
+ }
1435
+
1436
+ private getBEType(
1437
+ type: DyFM_BasicProperty_Type
1438
+ ): string | number | boolean | object | Function | Array<any> | Date {
1439
+ switch (type) {
1440
+ case DyFM_BasicProperty_Type.string:
1441
+ return String;
1442
+
1443
+ case DyFM_BasicProperty_Type.number:
1444
+ return Number;
1445
+
1446
+ case DyFM_BasicProperty_Type.boolean:
1447
+ return Boolean;
1448
+
1449
+ case DyFM_BasicProperty_Type.date:
1450
+ return Date;
1451
+
1452
+ case DyFM_BasicProperty_Type.object:
1453
+ return Object;
1454
+
1455
+ case DyFM_BasicProperty_Type.array:
1456
+ return Array;
1457
+
1458
+ case DyFM_BasicProperty_Type.function:
1459
+ return Function;
1460
+
1461
+ default:
1462
+ DyFM_Log.H_info('wtf', DyFM_Object.cleanObject(this.dataParams));
1463
+
1464
+ throw new DyFM_Error({
1465
+ error: new Error(
1466
+ `Invalid property type: "${type}" (${this.dataParams.dataName})` +
1467
+ (this.dataParams.constructed?.() ? '' : ('\nThe dataParams is not constructed properly! \n' +
1468
+ 'Use the DyFM_DataModel_Params.constructor to construct it properly!'))
1469
+ ),
1470
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-GTP0`,
1471
+ additionalContent: { type: type, dataParams: this.dataParams },
1472
+ __localStack: this.dataParams.stackLocation,
1473
+ });
1474
+ }
1475
+ /* switch (type.toLocaleLowerCase()) {
1476
+ case DyFM_BasicProperty_Type.string:
1477
+ case 'string':
1478
+ return String;
1479
+
1480
+ case DyFM_BasicProperty_Type.number:
1481
+ case 'number':
1482
+ return Number;
1483
+
1484
+ case DyFM_BasicProperty_Type.boolean:
1485
+ case 'boolean':
1486
+ return Boolean;
1487
+
1488
+ case DyFM_BasicProperty_Type.date:
1489
+ case 'date':
1490
+ return Date;
1491
+
1492
+ case DyFM_BasicProperty_Type.object:
1493
+ case 'object':
1494
+ return Object;
1495
+
1496
+ case DyFM_BasicProperty_Type.array:
1497
+ case 'array':
1498
+ return Array;
1499
+
1500
+ default:
1501
+ if (type.includes('[]') || type.includes('array')) {
1502
+ return Array;
1503
+ } else if (type.includes('=>') || type.includes('function')) {
1504
+ return Function;
1505
+ } else {
1506
+ return Object;
1507
+ }
1508
+ } */
1509
+ }
1510
+
1511
+ /**
1512
+ * adds dynamo metadata settings to any mongoose schema building settings object
1513
+ * @param schema schema to update
1514
+ * @returns updated schema
1515
+ */
1516
+ /* private addMetadataToSchema(schema: any): any {
1517
+ schema.__created = { type: Date };
1518
+ schema.__createdBy = { type: String };
1519
+ schema.__lastModified = { type: Date };
1520
+ schema.__lastModifiedBy = { type: String };
1521
+
1522
+ schema._deleted = { type: Date };
1523
+ schema._deletedBy = { type: String };
1524
+
1525
+ return schema;
1526
+ } */
1527
+
1528
+ /**
1529
+ * adds dynamo metadata settings to any mongoose schema building settings object
1530
+ * @param properties properties to update
1531
+ * @returns updated properties
1532
+ */
1533
+ private addMetadataToProperties(properties: DyFM_DataProperties<T>): DyFM_DataProperties<T> {
1534
+ // TOD: ezek a kikommentelt "required: true"-k kellenek, csak félő, hogy gondokat okoznak a
1535
+ // jelenlegi rendszerekben, ezért akkor kell majd visszarakni, ha lesz tesztelői ÉS fejlesztői kapacitás rá
1536
+ if (!properties.__created) {
1537
+ properties.__created = {
1538
+ key: '__created', type: DyFM_BasicProperty_Type.date/* , required: true */,
1539
+ };
1540
+ }
1541
+
1542
+ if (!properties.__createdBy) {
1543
+ properties.__createdBy = {
1544
+ key: '__createdBy', type: DyFM_BasicProperty_Type.string/* , required: true */,
1545
+ };
1546
+ }
1547
+
1548
+ if (!properties.__lastModified) {
1549
+ properties.__lastModified = {
1550
+ key: '__lastModified', type: DyFM_BasicProperty_Type.date/* , required: true */,
1551
+ };
1552
+ }
1553
+
1554
+ if (!properties.__lastModifiedBy) {
1555
+ properties.__lastModifiedBy = {
1556
+ key: '__lastModifiedBy', type: DyFM_BasicProperty_Type.string/* , required: true */,
1557
+ };
1558
+ }
1559
+
1560
+ if (!properties._deleted) {
1561
+ properties._deleted = {
1562
+ key: '_deleted', type: DyFM_BasicProperty_Type.date,
1563
+ };
1564
+ }
1565
+
1566
+ if (!properties._deletedBy) {
1567
+ properties._deletedBy = {
1568
+ key: '_deletedBy', type: DyFM_BasicProperty_Type.string,
1569
+ };
1570
+ }
1571
+
1572
+ if (!properties._archived) {
1573
+ properties._archived = {
1574
+ key: '_archived', type: DyFM_BasicProperty_Type.date,
1575
+ };
1576
+ }
1577
+
1578
+ return properties;
1579
+ }
1580
+
1581
+ /* private addArchiveMetadataToSchema(schema: any): any {
1582
+ schema._originalId = { type: String, required: true, index: true, unique: true };
1583
+ schema._archived = { type: Date, required: true };
1584
+
1585
+ return schema;
1586
+ } */
1587
+
1588
+ private addArchiveMetadataToProperties(
1589
+ properties: DyFM_DataProperties<T>
1590
+ ): DyFM_DataProperties<T> {
1591
+ if (!properties._originalId) {
1592
+ properties._originalId = {
1593
+ key: '_originalId', type: DyFM_BasicProperty_Type.string,
1594
+ required: true, index: true, unique: true,
1595
+ };
1596
+ }
1597
+
1598
+ if (!properties._archived) {
1599
+ properties._archived = {
1600
+ key: '_archived', type: DyFM_BasicProperty_Type.date,
1601
+ required: true,
1602
+ };
1603
+ } else if (properties._archived.required === undefined) {
1604
+ properties._archived.required = true;
1605
+ }
1606
+
1607
+ return properties;
1608
+ }
1609
+
1610
+ /**
1611
+ * sets depDataKey
1612
+ */
1613
+ private lookForDependencyDataSettings(): void {
1614
+ const dependencyParams: DyFM_DataProperty_Params<any, T>[] =
1615
+ Object.values(this.dataParams.properties).filter(
1616
+ (modelParams: DyFM_DataProperty_Params<any, T>): boolean =>
1617
+ Boolean(modelParams.dependencyDataName)
1618
+ );
1619
+
1620
+ if (dependencyParams) {
1621
+ this.depKeys.push(...dependencyParams.map(
1622
+ (dependencyParam: DyFM_DataProperty_Params<any, T>): string => dependencyParam.key
1623
+ ));
1624
+ }
1625
+ }
1626
+
1627
+ private async deleteThrowMethod(data: any, issuer?: string): Promise<void> {
1628
+ throw new DyFM_Error({
1629
+ error: new Error(`Forbidden to delete any data! (${this.dataParams.dataName})`),
1630
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CDAD`,
1631
+ additionalContent: { dataParams: this.dataParams, data: data },
1632
+ issuer: issuer,
1633
+ });
1634
+ };
1635
+
1636
+ private async modifyThrowMethod(data: any, issuer?: string): Promise<void> {
1637
+ throw new DyFM_Error({
1638
+ error: new Error(`Forbidden to modify any data! (${this.dataParams.dataName})`),
1639
+ errorCode: `${DyNTS_global_settings.systemShortCodeName}|DyNTS-DBS-CDAD`,
1640
+ additionalContent: { dataParams: this.dataParams, data: data },
1641
+ issuer: issuer,
1642
+ });
1643
+ }
1644
+ }