@autofleet/sadot 1.1.1 → 1.1.2-beta

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 (331) hide show
  1. package/.nvmrc +1 -0
  2. package/dist/api/index.d.ts +3 -0
  3. package/dist/api/index.js +12 -2
  4. package/dist/api/v1/definition/index.d.ts +3 -0
  5. package/dist/api/v1/definition/index.js +116 -2
  6. package/dist/api/v1/definition/validations.d.ts +2 -0
  7. package/dist/api/v1/definition/validations.js +77 -2
  8. package/dist/api/v1/errors.d.ts +4 -0
  9. package/dist/api/v1/errors.js +12 -2
  10. package/dist/api/v1/index.d.ts +3 -0
  11. package/dist/api/v1/index.js +13 -2
  12. package/dist/api/v1/validator/index.d.ts +3 -0
  13. package/dist/api/v1/validator/index.js +143 -2
  14. package/dist/api/v1/validator/validations.d.ts +6 -23
  15. package/dist/api/v1/validator/validations.js +38 -2
  16. package/dist/errors/index.d.ts +24 -0
  17. package/dist/errors/index.js +66 -3
  18. package/dist/events/index.d.ts +5 -0
  19. package/dist/events/index.js +54 -2
  20. package/dist/hooks/create.d.ts +10 -0
  21. package/dist/hooks/create.js +95 -0
  22. package/dist/hooks/enrich.d.ts +25 -0
  23. package/dist/hooks/enrich.js +198 -2
  24. package/dist/hooks/find.d.ts +1 -0
  25. package/dist/hooks/find.js +29 -2
  26. package/dist/hooks/hooks.d.ts +17 -0
  27. package/dist/hooks/hooks.js +391 -2
  28. package/dist/hooks/index.d.ts +5 -0
  29. package/dist/hooks/index.js +17 -1
  30. package/dist/hooks/update.d.ts +10 -0
  31. package/dist/hooks/update.js +49 -0
  32. package/dist/hooks/utils/updateInstanceValues.d.ts +15 -0
  33. package/dist/hooks/utils/updateInstanceValues.js +50 -2
  34. package/dist/hooks/workaround.d.ts +10 -0
  35. package/dist/hooks/workaround.js +37 -0
  36. package/dist/index.d.ts +12 -22
  37. package/dist/index.js +67 -2
  38. package/dist/models/CustomFieldDefinition.d.ts +23 -29
  39. package/dist/models/CustomFieldDefinition.js +192 -2
  40. package/dist/models/CustomFieldEntries.d.ts +13 -14
  41. package/dist/models/CustomFieldEntries.js +123 -2
  42. package/dist/models/CustomFieldValue.d.ts +14 -20
  43. package/dist/models/CustomFieldValue.js +151 -2
  44. package/dist/models/CustomValidator.d.ts +15 -17
  45. package/dist/models/CustomValidator.js +98 -2
  46. package/dist/models/index.d.ts +18 -6
  47. package/dist/models/index.js +131 -2
  48. package/dist/models/tests/AssociatedTestModel.d.ts +12 -0
  49. package/dist/models/tests/AssociatedTestModel.js +71 -2
  50. package/dist/models/tests/TestModel.d.ts +12 -0
  51. package/dist/models/tests/TestModel.js +69 -2
  52. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.d.ts +10 -0
  53. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.js +53 -2
  54. package/dist/models/tests/contextAwareModels/ContextTestModel.d.ts +13 -0
  55. package/dist/models/tests/contextAwareModels/ContextTestModel.js +47 -2
  56. package/dist/repository/definition.d.ts +36 -0
  57. package/dist/repository/definition.js +121 -2
  58. package/dist/repository/entries.d.ts +13 -0
  59. package/dist/repository/entries.js +92 -2
  60. package/dist/repository/utils/formatValues.d.ts +3 -0
  61. package/dist/repository/utils/formatValues.js +16 -2
  62. package/dist/repository/validator.d.ts +21 -0
  63. package/dist/repository/validator.js +62 -2
  64. package/dist/repository/value.d.ts +28 -0
  65. package/dist/repository/value.js +124 -2
  66. package/dist/scopes/filter.d.ts +29 -22
  67. package/dist/scopes/filter.js +75 -2
  68. package/dist/scopes/helpers/filter.helpers.d.ts +40 -15
  69. package/dist/scopes/helpers/filter.helpers.js +183 -25
  70. package/dist/scopes/index.d.ts +2 -0
  71. package/dist/scopes/index.js +6 -1
  72. package/dist/tests/api/test-api.d.ts +2 -0
  73. package/dist/tests/api/test-api.js +38 -0
  74. package/dist/tests/functional/searching/index.d.ts +8 -0
  75. package/dist/tests/functional/searching/index.js +44 -0
  76. package/dist/tests/helpers/commonHooks.d.ts +6 -0
  77. package/dist/tests/helpers/commonHooks.js +62 -0
  78. package/dist/tests/helpers/database-config.d.ts +16 -0
  79. package/dist/tests/helpers/database-config.js +17 -0
  80. package/dist/tests/helpers/index.d.ts +7 -0
  81. package/dist/tests/helpers/index.js +33 -0
  82. package/dist/tests/mocks/definition.mock.d.ts +48 -0
  83. package/dist/tests/mocks/definition.mock.js +78 -0
  84. package/dist/tests/mocks/events.mock.d.ts +4 -0
  85. package/dist/tests/mocks/events.mock.js +21 -0
  86. package/dist/tests/mocks/testModel.d.ts +12 -0
  87. package/dist/tests/mocks/testModel.js +35 -0
  88. package/dist/types/definition/index.d.ts +25 -0
  89. package/dist/types/definition/index.js +2 -0
  90. package/dist/types/entries/index.d.ts +25 -0
  91. package/dist/types/entries/index.js +2 -0
  92. package/dist/types/index.d.ts +46 -45
  93. package/dist/types/index.js +2 -0
  94. package/dist/types/value/index.d.ts +15 -0
  95. package/dist/types/value/index.js +2 -0
  96. package/dist/utils/constants/index.d.ts +17 -20
  97. package/dist/utils/constants/index.js +22 -2
  98. package/dist/utils/db/index.d.ts +4 -0
  99. package/dist/utils/db/index.js +24 -2
  100. package/dist/utils/helpers/index.d.ts +23 -28
  101. package/dist/utils/helpers/index.js +40 -2
  102. package/dist/utils/init.d.ts +7 -0
  103. package/dist/utils/init.js +111 -2
  104. package/dist/utils/logger/index.d.ts +3 -0
  105. package/dist/utils/logger/index.js +42 -2
  106. package/dist/utils/scopeAttributes.d.ts +2 -0
  107. package/dist/utils/scopeAttributes.js +11 -2
  108. package/dist/utils/validations/index.d.ts +8 -0
  109. package/dist/utils/validations/index.js +41 -2
  110. package/dist/utils/validations/schema/custom-fields.d.ts +2 -6
  111. package/dist/utils/validations/schema/custom-fields.js +9 -2
  112. package/dist/utils/validations/schema/validator-schema.d.ts +9 -0
  113. package/dist/utils/validations/schema/validator-schema.js +95 -2
  114. package/dist/utils/validations/type.d.ts +15 -0
  115. package/dist/utils/validations/type.js +2 -0
  116. package/dist/utils/validations/validators/index.d.ts +14 -0
  117. package/dist/utils/validations/validators/index.js +40 -2
  118. package/dist/utils/validations/validators/select.validator.d.ts +5 -0
  119. package/dist/utils/validations/validators/select.validator.js +12 -2
  120. package/dist/utils/validations/validators/status.validator.d.ts +12 -0
  121. package/dist/utils/validations/validators/status.validator.js +15 -2
  122. package/package.json +39 -40
  123. package/src/api/index.ts +10 -0
  124. package/src/api/v1/definition/index.ts +104 -0
  125. package/src/api/v1/definition/validations.ts +75 -0
  126. package/src/api/v1/errors.ts +13 -0
  127. package/src/api/v1/index.ts +11 -0
  128. package/src/api/v1/validator/index.ts +141 -0
  129. package/src/api/v1/validator/validations.ts +38 -0
  130. package/src/errors/index.ts +70 -0
  131. package/src/events/index.ts +63 -0
  132. package/src/hooks/create.ts +81 -0
  133. package/src/hooks/enrich.ts +255 -0
  134. package/src/hooks/find.ts +27 -0
  135. package/src/hooks/hooks.ts +482 -0
  136. package/src/hooks/index.ts +20 -0
  137. package/src/hooks/update.ts +55 -0
  138. package/src/hooks/utils/updateInstanceValues.ts +63 -0
  139. package/src/hooks/workaround.ts +47 -0
  140. package/src/index.ts +52 -0
  141. package/src/models/CustomFieldDefinition.ts +162 -0
  142. package/src/models/CustomFieldEntries.ts +81 -0
  143. package/src/models/CustomFieldValue.ts +118 -0
  144. package/src/models/CustomValidator.ts +78 -0
  145. package/src/models/index.ts +165 -0
  146. package/src/models/tests/AssociatedTestModel.ts +57 -0
  147. package/src/models/tests/TestModel.ts +54 -0
  148. package/src/models/tests/contextAwareModels/ContextAwareTestModel.ts +43 -0
  149. package/src/models/tests/contextAwareModels/ContextTestModel.ts +38 -0
  150. package/src/repository/definition.ts +175 -0
  151. package/src/repository/entries.ts +88 -0
  152. package/src/repository/utils/formatValues.ts +14 -0
  153. package/src/repository/validator.ts +104 -0
  154. package/src/repository/value.ts +116 -0
  155. package/src/scopes/filter.ts +100 -0
  156. package/src/scopes/helpers/filter.helpers.ts +227 -0
  157. package/src/scopes/index.ts +6 -0
  158. package/src/tests/api/test-api.ts +40 -0
  159. package/src/tests/functional/searching/index.ts +39 -0
  160. package/src/tests/helpers/commonHooks.ts +43 -0
  161. package/src/tests/helpers/database-config.ts +15 -0
  162. package/src/tests/helpers/index.ts +35 -0
  163. package/src/tests/mocks/definition.mock.ts +84 -0
  164. package/src/tests/mocks/events.mock.ts +21 -0
  165. package/src/tests/mocks/testModel.ts +37 -0
  166. package/src/types/definition/index.ts +24 -0
  167. package/src/types/entries/index.ts +27 -0
  168. package/src/types/index.ts +52 -0
  169. package/src/types/value/index.ts +14 -0
  170. package/src/utils/constants/index.ts +25 -0
  171. package/src/utils/db/index.ts +21 -0
  172. package/src/utils/helpers/index.ts +66 -0
  173. package/src/utils/init.ts +120 -0
  174. package/src/utils/logger/index.ts +14 -0
  175. package/src/utils/scopeAttributes.ts +12 -0
  176. package/src/utils/validations/index.ts +46 -0
  177. package/src/utils/validations/schema/README.md +93 -0
  178. package/src/utils/validations/schema/custom-fields.ts +8 -0
  179. package/src/utils/validations/schema/validator-schema.ts +106 -0
  180. package/src/utils/validations/type.ts +20 -0
  181. package/src/utils/validations/validators/index.ts +38 -0
  182. package/src/utils/validations/validators/select.validator.ts +12 -0
  183. package/src/utils/validations/validators/status.validator.ts +22 -0
  184. package/tsconfig.build.json +7 -0
  185. package/tsconfig.json +16 -0
  186. package/dist/_virtual/_@oxc-project_runtime@0.97.0/helpers/decorate.cjs +0 -1
  187. package/dist/_virtual/_@oxc-project_runtime@0.97.0/helpers/decorate.js +0 -1
  188. package/dist/_virtual/_@oxc-project_runtime@0.97.0/helpers/decorateMetadata.cjs +0 -1
  189. package/dist/_virtual/_@oxc-project_runtime@0.97.0/helpers/decorateMetadata.js +0 -1
  190. package/dist/_virtual/rolldown_runtime.cjs +0 -1
  191. package/dist/api/index.cjs +0 -2
  192. package/dist/api/index.cjs.map +0 -1
  193. package/dist/api/index.js.map +0 -1
  194. package/dist/api/v1/definition/index.cjs +0 -2
  195. package/dist/api/v1/definition/index.cjs.map +0 -1
  196. package/dist/api/v1/definition/index.js.map +0 -1
  197. package/dist/api/v1/definition/validations.cjs +0 -2
  198. package/dist/api/v1/definition/validations.cjs.map +0 -1
  199. package/dist/api/v1/definition/validations.js.map +0 -1
  200. package/dist/api/v1/errors.cjs +0 -2
  201. package/dist/api/v1/errors.cjs.map +0 -1
  202. package/dist/api/v1/errors.js.map +0 -1
  203. package/dist/api/v1/index.cjs +0 -2
  204. package/dist/api/v1/index.cjs.map +0 -1
  205. package/dist/api/v1/index.js.map +0 -1
  206. package/dist/api/v1/validator/index.cjs +0 -2
  207. package/dist/api/v1/validator/index.cjs.map +0 -1
  208. package/dist/api/v1/validator/index.js.map +0 -1
  209. package/dist/api/v1/validator/validations.cjs +0 -2
  210. package/dist/api/v1/validator/validations.cjs.map +0 -1
  211. package/dist/api/v1/validator/validations.d.cts +0 -23
  212. package/dist/api/v1/validator/validations.js.map +0 -1
  213. package/dist/errors/index.cjs +0 -3
  214. package/dist/errors/index.cjs.map +0 -1
  215. package/dist/errors/index.js.map +0 -1
  216. package/dist/events/index.cjs +0 -2
  217. package/dist/events/index.cjs.map +0 -1
  218. package/dist/events/index.js.map +0 -1
  219. package/dist/hooks/enrich.cjs +0 -2
  220. package/dist/hooks/enrich.cjs.map +0 -1
  221. package/dist/hooks/enrich.js.map +0 -1
  222. package/dist/hooks/find.cjs +0 -2
  223. package/dist/hooks/find.cjs.map +0 -1
  224. package/dist/hooks/find.js.map +0 -1
  225. package/dist/hooks/hooks.cjs +0 -2
  226. package/dist/hooks/hooks.cjs.map +0 -1
  227. package/dist/hooks/hooks.js.map +0 -1
  228. package/dist/hooks/index.cjs +0 -1
  229. package/dist/hooks/utils/updateInstanceValues.cjs +0 -2
  230. package/dist/hooks/utils/updateInstanceValues.cjs.map +0 -1
  231. package/dist/hooks/utils/updateInstanceValues.js.map +0 -1
  232. package/dist/index.cjs +0 -2
  233. package/dist/index.cjs.map +0 -1
  234. package/dist/index.d.cts +0 -23
  235. package/dist/index.js.map +0 -1
  236. package/dist/models/CustomFieldDefinition.cjs +0 -2
  237. package/dist/models/CustomFieldDefinition.cjs.map +0 -1
  238. package/dist/models/CustomFieldDefinition.d.cts +0 -31
  239. package/dist/models/CustomFieldDefinition.js.map +0 -1
  240. package/dist/models/CustomFieldEntries.cjs +0 -2
  241. package/dist/models/CustomFieldEntries.cjs.map +0 -1
  242. package/dist/models/CustomFieldEntries.d.cts +0 -16
  243. package/dist/models/CustomFieldEntries.js.map +0 -1
  244. package/dist/models/CustomFieldValue.cjs +0 -2
  245. package/dist/models/CustomFieldValue.cjs.map +0 -1
  246. package/dist/models/CustomFieldValue.d.cts +0 -22
  247. package/dist/models/CustomFieldValue.js.map +0 -1
  248. package/dist/models/CustomValidator.cjs +0 -2
  249. package/dist/models/CustomValidator.cjs.map +0 -1
  250. package/dist/models/CustomValidator.d.cts +0 -19
  251. package/dist/models/CustomValidator.js.map +0 -1
  252. package/dist/models/index.cjs +0 -2
  253. package/dist/models/index.cjs.map +0 -1
  254. package/dist/models/index.d.cts +0 -6
  255. package/dist/models/index.js.map +0 -1
  256. package/dist/models/tests/AssociatedTestModel.cjs +0 -2
  257. package/dist/models/tests/AssociatedTestModel.cjs.map +0 -1
  258. package/dist/models/tests/AssociatedTestModel.js.map +0 -1
  259. package/dist/models/tests/TestModel.cjs +0 -2
  260. package/dist/models/tests/TestModel.cjs.map +0 -1
  261. package/dist/models/tests/TestModel.js.map +0 -1
  262. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.cjs +0 -2
  263. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.cjs.map +0 -1
  264. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.js.map +0 -1
  265. package/dist/models/tests/contextAwareModels/ContextTestModel.cjs +0 -2
  266. package/dist/models/tests/contextAwareModels/ContextTestModel.cjs.map +0 -1
  267. package/dist/models/tests/contextAwareModels/ContextTestModel.js.map +0 -1
  268. package/dist/repository/definition.cjs +0 -2
  269. package/dist/repository/definition.cjs.map +0 -1
  270. package/dist/repository/definition.js.map +0 -1
  271. package/dist/repository/entries.cjs +0 -2
  272. package/dist/repository/entries.cjs.map +0 -1
  273. package/dist/repository/entries.js.map +0 -1
  274. package/dist/repository/utils/formatValues.cjs +0 -2
  275. package/dist/repository/utils/formatValues.cjs.map +0 -1
  276. package/dist/repository/utils/formatValues.js.map +0 -1
  277. package/dist/repository/validator.cjs +0 -2
  278. package/dist/repository/validator.cjs.map +0 -1
  279. package/dist/repository/validator.js.map +0 -1
  280. package/dist/repository/value.cjs +0 -2
  281. package/dist/repository/value.cjs.map +0 -1
  282. package/dist/repository/value.js.map +0 -1
  283. package/dist/scopes/filter.cjs +0 -2
  284. package/dist/scopes/filter.cjs.map +0 -1
  285. package/dist/scopes/filter.d.cts +0 -23
  286. package/dist/scopes/filter.js.map +0 -1
  287. package/dist/scopes/helpers/filter.helpers.cjs +0 -46
  288. package/dist/scopes/helpers/filter.helpers.cjs.map +0 -1
  289. package/dist/scopes/helpers/filter.helpers.d.cts +0 -17
  290. package/dist/scopes/helpers/filter.helpers.js.map +0 -1
  291. package/dist/scopes/index.cjs +0 -1
  292. package/dist/types/index.d.cts +0 -45
  293. package/dist/utils/constants/index.cjs +0 -2
  294. package/dist/utils/constants/index.cjs.map +0 -1
  295. package/dist/utils/constants/index.d.cts +0 -22
  296. package/dist/utils/constants/index.js.map +0 -1
  297. package/dist/utils/db/index.cjs +0 -2
  298. package/dist/utils/db/index.cjs.map +0 -1
  299. package/dist/utils/db/index.js.map +0 -1
  300. package/dist/utils/helpers/index.cjs +0 -2
  301. package/dist/utils/helpers/index.cjs.map +0 -1
  302. package/dist/utils/helpers/index.d.cts +0 -31
  303. package/dist/utils/helpers/index.js.map +0 -1
  304. package/dist/utils/init.cjs +0 -2
  305. package/dist/utils/init.cjs.map +0 -1
  306. package/dist/utils/init.js.map +0 -1
  307. package/dist/utils/logger/index.cjs +0 -2
  308. package/dist/utils/logger/index.cjs.map +0 -1
  309. package/dist/utils/logger/index.js.map +0 -1
  310. package/dist/utils/scopeAttributes.cjs +0 -2
  311. package/dist/utils/scopeAttributes.cjs.map +0 -1
  312. package/dist/utils/scopeAttributes.js.map +0 -1
  313. package/dist/utils/validations/index.cjs +0 -2
  314. package/dist/utils/validations/index.cjs.map +0 -1
  315. package/dist/utils/validations/index.js.map +0 -1
  316. package/dist/utils/validations/schema/custom-fields.cjs +0 -2
  317. package/dist/utils/validations/schema/custom-fields.cjs.map +0 -1
  318. package/dist/utils/validations/schema/custom-fields.d.cts +0 -7
  319. package/dist/utils/validations/schema/custom-fields.js.map +0 -1
  320. package/dist/utils/validations/schema/validator-schema.cjs +0 -2
  321. package/dist/utils/validations/schema/validator-schema.cjs.map +0 -1
  322. package/dist/utils/validations/schema/validator-schema.js.map +0 -1
  323. package/dist/utils/validations/validators/index.cjs +0 -2
  324. package/dist/utils/validations/validators/index.cjs.map +0 -1
  325. package/dist/utils/validations/validators/index.js.map +0 -1
  326. package/dist/utils/validations/validators/select.validator.cjs +0 -2
  327. package/dist/utils/validations/validators/select.validator.cjs.map +0 -1
  328. package/dist/utils/validations/validators/select.validator.js.map +0 -1
  329. package/dist/utils/validations/validators/status.validator.cjs +0 -2
  330. package/dist/utils/validations/validators/status.validator.cjs.map +0 -1
  331. package/dist/utils/validations/validators/status.validator.js.map +0 -1
@@ -1,2 +1,391 @@
1
- import e from"../utils/logger/index.js";import{CustomFieldDefinitionType as t}from"../utils/constants/index.js";import{InvalidValueError as n,MissingRequiredCustomFieldError as r}from"../errors/index.js";import{findAll as i}from"../repository/definition.js";import{findAllByModelType as a}from"../repository/validator.js";import o from"../utils/scopeAttributes.js";import s from"./utils/updateInstanceValues.js";import c from"joi";import{BadRequest as l}from"@autofleet/errors";import u from"ajv";import d from"ajv-formats";import f from"ajv-errors";const p=[`id`,`schema`,`modelType`,`entityId`,`disabled`],m=new u({allErrors:!0,strict:!1,strictTypes:!1,$data:!0});d(m),f(m);const h=(e,t)=>({__proto__:null,...e,...t}),g=async(t,n)=>{if(!t.id||!t.customFields||Object.keys(t.customFields).length===0)return t.customFields||{};try{let r=await t.constructor.findOne({where:{id:t.id},attributes:[`customFields`],transaction:n.transaction,raw:!0});if(r?.customFields){let n=h(r.customFields,t.customFields);return e.debug(`sadot - fetched complete custom fields for validation`,{fieldsCount:Object.keys(n).length,updateFieldsCount:Object.keys(t.customFields).length}),n}}catch(t){e.error(`sadot - error fetching complete model for validation`,{error:t})}return t.customFields||{}},_=e=>{let t={...e.dataValues};(e.changed?.()||[]).forEach(n=>{let r=e.previous?.(n);r!==void 0&&(t[n]=r)});let n=e.previous?.(`customFields`);return n!==void 0&&(t.customFields=n),t},v=e=>e.reduce((e,t)=>{let n=((t.instancePath||``).split(`/`).filter(Boolean).join(`.`).replace(/^after\./,``)+(t.keyword===`required`?`.${t.params?.missingProperty}`:``)).replace(/^\./,``)||`root`;return e[n]=t.message||`Invalid value`,e},{}),y=async(t,n,r,i={},s=!1)=>{let c=t.constructor.name;e.debug(`sadot - validating model`,{isCreate:s,modelType:c});let u=o(t,r);if(e.debug(`sadot - identifiers`,{identifiers:u}),!u||Object.keys(u).length===0){e.debug(`sadot - skipping validation: no identifiers`);return}let d=Object.values(u)[0];if(e.debug(`sadot - entityId`,{entityId:d}),!d){e.debug(`sadot - skipping validation: no entityId`);return}let f,y;n.transaction&&(n.transaction.validationsCache??=new Map,y=`${c}-${d}`,f=n.transaction.validationsCache.get(y)),f||(f=a(c,d,{transaction:n.transaction,attributes:p,modelOptions:i}),n.transaction&&n?.transaction?.validationsCache.set(y,f));let b=await f;if(e.debug(`sadot - validators found`,{count:b.length}),!b.length){e.debug(`sadot - skipping validation: no validators found`);return}let x=null;s||(x=_(t));let S=s?t.customFields||{}:await g(t,n);for(let n of b){let{schema:r}=n,i=r;if(e.debug(`sadot - validating with schema`,{schema:r,hasAfterProps:!!i.properties?.after,hasBeforeProps:!!i.properties?.before}),s){if(i.properties?.after){let e=m.compile({...r,properties:{after:i.properties.after}});if(!e(JSON.parse(JSON.stringify({after:{...t.dataValues,customFields:S}})))){let t=e.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid value`}`).join(`, `),n=v(e.errors);throw new l([Error(`Validation failed for ${c}: ${t}`)],void 0,{customError:n})}}}else{let n=m.compile(i),r=h(t.dataValues);r.customFields=S;let a={before:x,after:r},o=n(JSON.parse(JSON.stringify(a)));if(e.debug(`sadot - validation result`,{isValid:o,test:{before:x,after:r}}),!o){let e=n.errors?.map(e=>`${e.instancePath||``} ${e.message||`Invalid value`}`).join(`, `),t=v(n.errors);throw new l([Error(`Validation failed for ${c}: ${e}`)],void 0,{customError:t})}}}},b=async({modelType:e,modelOptions:t,identifiers:n,options:r})=>{let{include:a,useEntityIdFromInclude:o}=t;return await i({modelType:e,disabled:!1,...!o&&{entityId:n}},{withDisabled:!1,transaction:r.transaction,include:a?.(n)})},x=(e,r)=>{(e||[]).forEach(e=>{let{fieldType:i,name:a}=e;if([t.DATE,t.DATETIME].includes(i)){let e=r.customFields?.[a];if(e){let{value:t,error:i}=c.date().validate(e);if(i)throw new n(e,a,i);r.customFields[a]=t.toISOString()}}})},S=(t,n={},i={useCustomFieldsEntries:!1})=>async(a,c)=>{e.debug(`sadot - before create hook`);let{fields:l}=c,u=a.constructor.name,d=o(a,t),f=await b({modelType:u,modelOptions:n,identifiers:d,options:c}),p=f.filter(e=>![null,void 0].includes(e.defaultValue));p.length&&(a.customFields||={},p.filter(e=>a.customFields?.[e.name]===void 0).forEach(({name:e,defaultValue:t})=>{a.customFields[e]=t}));let m=Array.from(new Set(f.filter(({required:e})=>e).map(({name:e})=>e))),{customFields:h}=a,g=Object.keys(h??{}),_=m.filter(e=>!g.includes(e));if(_?.length)throw new r(_);await y(a,c,t,n,!0),x(f,a);let v=l.indexOf(`customFields`);v===-1||!h||!Object.keys(h).length||(await s({modelId:a.id,modelType:u,identifiers:d,customFields:h,options:{useCustomFieldsEntries:i.useCustomFieldsEntries,transaction:c.transaction,modelOptions:n}}),l.splice(v,1))},C=(t,n={},r={useCustomFieldsEntries:!1})=>async(i,a)=>{e.debug(`sadot - before update hook`);let{fields:c}=a,l=i.constructor.name,u=o(i,t),d=await b({modelType:l,modelOptions:n,identifiers:u,options:a});await y(i,a,t,n,!1),x(d,i);let f=c.indexOf(`customFields`);if(f>-1){let{customFields:e}=i;if(!Object.keys(e).length)return;await s({modelId:i.id,modelType:l,identifiers:u,customFields:e,options:{useCustomFieldsEntries:r.useCustomFieldsEntries,transaction:a.transaction,modelOptions:n}}),c.splice(f,1)}},w=e=>{e.individualHooks=!0},T=e=>{e.individualHooks=!0};export{w as beforeBulkCreate,T as beforeBulkUpdate,S as beforeCreate,C as beforeUpdate};
2
- //# sourceMappingURL=hooks.js.map
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.beforeBulkUpdate = exports.beforeBulkCreate = exports.beforeUpdate = exports.beforeCreate = void 0;
30
+ const ajv_1 = __importDefault(require("ajv"));
31
+ const joi_1 = __importDefault(require("joi"));
32
+ const ajv_formats_1 = __importDefault(require("ajv-formats"));
33
+ const errors_1 = require("@autofleet/errors");
34
+ const ajv_errors_1 = __importDefault(require("ajv-errors"));
35
+ const logger_1 = __importDefault(require("../utils/logger"));
36
+ const ValidatorRepo = __importStar(require("../repository/validator"));
37
+ const DefinitionRepo = __importStar(require("../repository/definition"));
38
+ const errors_2 = require("../errors");
39
+ const scopeAttributes_1 = __importDefault(require("../utils/scopeAttributes"));
40
+ const updateInstanceValues_1 = __importDefault(require("./utils/updateInstanceValues"));
41
+ const constants_1 = require("../utils/constants");
42
+ // Include all required fields for proper validation
43
+ const CUSTOM_VALIDATOR_ATTRIBUTES_TO_PULL = ['id', 'schema', 'modelType', 'entityId', 'disabled'];
44
+ // Initialize Ajv with relaxed settings to avoid warnings
45
+ const ajv = new ajv_1.default({
46
+ allErrors: true,
47
+ strict: false, // Disable strict mode to avoid warnings
48
+ strictTypes: false, // Disable strict type checking
49
+ $data: true, // Enable $data references
50
+ });
51
+ (0, ajv_formats_1.default)(ajv);
52
+ (0, ajv_errors_1.default)(ajv);
53
+ /**
54
+ * Helper function to manually copy object properties
55
+ * This is more efficient for large objects and avoids excessive object creation
56
+ */
57
+ // eslint-disable-next-line prefer-object-spread
58
+ const manualObjectCopy = (sourceObj, additionalProps) => ({ __proto__: null, ...sourceObj, ...additionalProps });
59
+ /**
60
+ * Fetches complete custom fields for an instance by merging DB values with update values
61
+ * This is needed for partial updates to ensure all related fields are available for validation
62
+ */
63
+ const getCompleteCustomFields = async (instance, options) => {
64
+ // If we don't have an instance id or no custom fields being updated, return original fields
65
+ if (!instance.id || !instance.customFields || Object.keys(instance.customFields).length === 0) {
66
+ return instance.customFields || {};
67
+ }
68
+ try {
69
+ const ModelClass = instance.constructor;
70
+ // Only select the customFields column to minimize data transfer
71
+ const currentCustomFields = await ModelClass.findOne({
72
+ where: { id: instance.id },
73
+ attributes: ['customFields'],
74
+ transaction: options.transaction,
75
+ raw: true, // Get plain object instead of model instance for better performance
76
+ });
77
+ if (currentCustomFields?.customFields) {
78
+ // Merge existing fields with update fields using our helper function
79
+ const completeFields = manualObjectCopy(currentCustomFields.customFields, instance.customFields);
80
+ logger_1.default.debug('sadot - fetched complete custom fields for validation', {
81
+ fieldsCount: Object.keys(completeFields).length,
82
+ updateFieldsCount: Object.keys(instance.customFields).length,
83
+ });
84
+ return completeFields;
85
+ }
86
+ }
87
+ catch (error) {
88
+ logger_1.default.error('sadot - error fetching complete model for validation', { error });
89
+ // Continue with partial data if we can't fetch the complete model
90
+ }
91
+ return instance.customFields || {};
92
+ };
93
+ const buildBeforeFromInstance = (instance) => {
94
+ const beforeFull = { ...instance.dataValues };
95
+ const changedKeys = instance.changed?.() || [];
96
+ changedKeys.forEach((key) => {
97
+ const prevVal = instance.previous?.(key);
98
+ if (prevVal !== undefined) {
99
+ beforeFull[key] = prevVal;
100
+ }
101
+ });
102
+ const prevCF = instance.previous?.('customFields');
103
+ if (prevCF !== undefined) {
104
+ beforeFull.customFields = prevCF;
105
+ }
106
+ return beforeFull;
107
+ };
108
+ const formatAjvErrors = (errors) => errors.reduce((acc, err) => {
109
+ const basePath = (err.instancePath || '')
110
+ .split('/')
111
+ .filter(Boolean)
112
+ .join('.')
113
+ .replace(/^after\./, '');
114
+ const missingProp = err.keyword === 'required' ? `.${err.params?.missingProperty}` : '';
115
+ const key = (basePath + missingProp).replace(/^\./, '') || 'root';
116
+ const message = err.message || 'Invalid value';
117
+ acc[key] = message;
118
+ return acc;
119
+ }, {});
120
+ /**
121
+ * Validates the model using custom validators
122
+ */
123
+ const validateModel = async (instance, options, scopeAttributes, modelOptions = {}, isCreate = false) => {
124
+ var _a;
125
+ const modelType = instance.constructor.name;
126
+ logger_1.default.debug('sadot - validating model', { isCreate, modelType });
127
+ const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
128
+ logger_1.default.debug('sadot - identifiers', { identifiers });
129
+ // Skip if no identifiers
130
+ if (!identifiers || Object.keys(identifiers).length === 0) {
131
+ logger_1.default.debug('sadot - skipping validation: no identifiers');
132
+ return;
133
+ }
134
+ // Find the entityId from identifiers (fleetId, businessModelId, etc.)
135
+ const entityId = Object.values(identifiers)[0]; // Get the first value as entityId
136
+ logger_1.default.debug('sadot - entityId', { entityId });
137
+ if (!entityId) {
138
+ logger_1.default.debug('sadot - skipping validation: no entityId');
139
+ return;
140
+ }
141
+ let validatorsPromise;
142
+ let cacheKey;
143
+ if (options.transaction) {
144
+ // eslint-disable-next-line no-param-reassign
145
+ (_a = options.transaction).validationsCache || (_a.validationsCache = new Map());
146
+ cacheKey = `${modelType}-${entityId}`;
147
+ validatorsPromise = options.transaction.validationsCache.get(cacheKey);
148
+ }
149
+ if (!validatorsPromise) {
150
+ validatorsPromise = ValidatorRepo.findAllByModelType(modelType, entityId, {
151
+ transaction: options.transaction,
152
+ attributes: CUSTOM_VALIDATOR_ATTRIBUTES_TO_PULL,
153
+ ...(modelOptions.include && {
154
+ include: modelOptions.include?.(entityId),
155
+ }),
156
+ raw: true,
157
+ });
158
+ if (options.transaction) {
159
+ options?.transaction?.validationsCache.set(cacheKey, validatorsPromise);
160
+ }
161
+ }
162
+ const validators = await validatorsPromise;
163
+ logger_1.default.debug('sadot - validators found', { count: validators.length });
164
+ if (!validators.length) {
165
+ logger_1.default.debug('sadot - skipping validation: no validators found');
166
+ return;
167
+ }
168
+ // For updates, get the previous values
169
+ let originalValues = null;
170
+ if (!isCreate) {
171
+ originalValues = buildBeforeFromInstance(instance);
172
+ }
173
+ // Get complete custom fields by merging DB values with update values
174
+ // This is especially important for partial updates to ensure all related fields are available
175
+ const completeCustomFields = !isCreate
176
+ ? await getCompleteCustomFields(instance, options)
177
+ : instance.customFields || {};
178
+ // eslint-disable-next-line no-restricted-syntax
179
+ for (const validator of validators) {
180
+ const { schema } = validator;
181
+ const typedSchema = schema;
182
+ logger_1.default.debug('sadot - validating with schema', {
183
+ schema,
184
+ hasAfterProps: !!typedSchema.properties?.after,
185
+ hasBeforeProps: !!typedSchema.properties?.before,
186
+ });
187
+ if (isCreate) {
188
+ // For create operations, we only need the 'after' state
189
+ if (typedSchema.properties?.after) {
190
+ const validateSchema = ajv.compile({
191
+ ...schema,
192
+ // Focus only on the 'after' validation part for create
193
+ properties: {
194
+ after: typedSchema.properties.after,
195
+ },
196
+ });
197
+ const isValid = validateSchema(JSON.parse(JSON.stringify({
198
+ after: {
199
+ ...instance.dataValues,
200
+ customFields: completeCustomFields,
201
+ },
202
+ })));
203
+ if (!isValid) {
204
+ const errorDetails = validateSchema.errors?.map((err) => `${err.instancePath || ''} ${err.message || 'Invalid value'}`).join(', ');
205
+ const formattedErrors = formatAjvErrors(validateSchema.errors);
206
+ throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)], undefined, {
207
+ customError: formattedErrors,
208
+ });
209
+ }
210
+ }
211
+ }
212
+ else {
213
+ // For update operations, we need both before and after
214
+ const validateSchema = ajv.compile(typedSchema);
215
+ // Create after object with our helper function
216
+ const afterObj = manualObjectCopy(instance.dataValues);
217
+ // Add complete custom fields
218
+ afterObj.customFields = completeCustomFields;
219
+ // Create validation payload
220
+ const payload = {
221
+ before: originalValues,
222
+ after: afterObj,
223
+ };
224
+ // Validate
225
+ const isValid = validateSchema(JSON.parse(JSON.stringify(payload)));
226
+ logger_1.default.debug('sadot - validation result', {
227
+ isValid,
228
+ test: {
229
+ before: originalValues,
230
+ after: afterObj,
231
+ },
232
+ });
233
+ if (!isValid) {
234
+ const errorDetails = validateSchema
235
+ .errors
236
+ ?.map((err) => `${err.instancePath || ''} ${err.message || 'Invalid value'}`).join(', ');
237
+ const formattedErrors = formatAjvErrors(validateSchema.errors);
238
+ throw new errors_1.BadRequest([new Error(`Validation failed for ${modelType}: ${errorDetails}`)], undefined, {
239
+ customError: formattedErrors,
240
+ });
241
+ }
242
+ }
243
+ }
244
+ };
245
+ const getFieldDefinitions = async ({ modelType, modelOptions, identifiers, options, }) => {
246
+ const { include, useEntityIdFromInclude } = modelOptions;
247
+ const where = {
248
+ modelType,
249
+ disabled: false,
250
+ ...(!useEntityIdFromInclude && { entityId: identifiers }),
251
+ };
252
+ const fieldDefinitions = await DefinitionRepo.findAll(where, {
253
+ withDisabled: false,
254
+ transaction: options.transaction,
255
+ include: include?.(identifiers),
256
+ });
257
+ return fieldDefinitions;
258
+ };
259
+ const formatDates = (fieldDefinitions, instance) => {
260
+ (fieldDefinitions || []).forEach((fieldDefinition) => {
261
+ const { fieldType, name } = fieldDefinition;
262
+ if ([constants_1.CustomFieldDefinitionType.DATE, constants_1.CustomFieldDefinitionType.DATETIME].includes(fieldType)) {
263
+ const value = instance.customFields?.[name];
264
+ if (value) {
265
+ const { value: joiValue, error: validationError } = joi_1.default.date().validate(value);
266
+ if (validationError) {
267
+ throw new errors_2.InvalidValueError(value, name, validationError);
268
+ }
269
+ // eslint-disable-next-line no-param-reassign
270
+ instance.customFields[name] = joiValue.toISOString();
271
+ }
272
+ }
273
+ });
274
+ };
275
+ /**
276
+ * Hook to handle validation and custom fields during creation
277
+ */
278
+ const beforeCreate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instance, options) => {
279
+ logger_1.default.debug('sadot - before create hook');
280
+ const { fields } = options;
281
+ const modelType = instance.constructor.name;
282
+ const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
283
+ // Step 1: Handle custom fields default values and required fields
284
+ const fieldDefinitions = await getFieldDefinitions({
285
+ modelType, modelOptions, identifiers, options,
286
+ });
287
+ // Apply default values
288
+ const fieldsWithDefaultValue = fieldDefinitions.filter((def) => ![null, undefined].includes(def.defaultValue));
289
+ if (fieldsWithDefaultValue.length) {
290
+ // eslint-disable-next-line no-param-reassign
291
+ instance.customFields || (instance.customFields = {});
292
+ fieldsWithDefaultValue
293
+ .filter((def) => (instance.customFields?.[def.name] === undefined))
294
+ .forEach(({ name, defaultValue }) => {
295
+ // eslint-disable-next-line no-param-reassign
296
+ instance.customFields[name] = defaultValue;
297
+ });
298
+ }
299
+ // Check for required fields
300
+ const requiredFieldsNames = Array.from(new Set(fieldDefinitions.filter(({ required }) => required).map(({ name }) => name)));
301
+ const { customFields } = instance;
302
+ const fieldsNames = Object.keys(customFields ?? {});
303
+ const missingFields = requiredFieldsNames.filter((name) => !fieldsNames.includes(name));
304
+ if (missingFields?.length) {
305
+ throw new errors_2.MissingRequiredCustomFieldError(missingFields);
306
+ }
307
+ // Step 2: Validate the model data (including custom fields)
308
+ await validateModel(instance, options, scopeAttributes, modelOptions, true);
309
+ // format date and datetime fields
310
+ formatDates(fieldDefinitions, instance);
311
+ // Step 3: Save custom field values if they exist
312
+ const customFieldsIdx = fields.indexOf('customFields');
313
+ if (customFieldsIdx === -1 || !customFields || !Object.keys(customFields).length) {
314
+ // No custom fields to update
315
+ return;
316
+ }
317
+ // Save custom field values
318
+ await (0, updateInstanceValues_1.default)({
319
+ modelId: instance.id,
320
+ modelType,
321
+ identifiers,
322
+ customFields,
323
+ options: {
324
+ useCustomFieldsEntries: sadotOptions.useCustomFieldsEntries,
325
+ transaction: options.transaction,
326
+ modelOptions,
327
+ },
328
+ });
329
+ // Remove customFields from fields array after handling
330
+ // eslint-disable-next-line no-param-reassign
331
+ fields.splice(customFieldsIdx, 1);
332
+ };
333
+ exports.beforeCreate = beforeCreate;
334
+ /**
335
+ * Hook to handle validation and custom fields during update
336
+ */
337
+ const beforeUpdate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instance, options) => {
338
+ logger_1.default.debug('sadot - before update hook');
339
+ const { fields } = options;
340
+ const modelType = instance.constructor.name;
341
+ const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
342
+ const fieldDefinitions = await getFieldDefinitions({
343
+ modelType, modelOptions, identifiers, options,
344
+ });
345
+ // Step 1: Validate the model data (including custom fields)
346
+ await validateModel(instance, options, scopeAttributes, modelOptions, false);
347
+ // format date and datetime fields
348
+ formatDates(fieldDefinitions, instance);
349
+ // Step 2: Update custom field values if they exist
350
+ const customFieldsIdx = fields.indexOf('customFields');
351
+ if (customFieldsIdx > -1) {
352
+ const { customFields } = instance;
353
+ if (!Object.keys(customFields).length) {
354
+ return;
355
+ }
356
+ // Save custom field values
357
+ await (0, updateInstanceValues_1.default)({
358
+ modelId: instance.id,
359
+ modelType,
360
+ identifiers,
361
+ customFields,
362
+ options: {
363
+ useCustomFieldsEntries: sadotOptions.useCustomFieldsEntries,
364
+ transaction: options.transaction,
365
+ modelOptions,
366
+ },
367
+ });
368
+ // Remove customFields from fields array after handling
369
+ // eslint-disable-next-line no-param-reassign
370
+ fields.splice(customFieldsIdx, 1);
371
+ }
372
+ };
373
+ exports.beforeUpdate = beforeUpdate;
374
+ /**
375
+ * Hook to enable individual hooks for bulk create operations
376
+ */
377
+ const beforeBulkCreate = (options) => {
378
+ // This will activate the beforeCreate hook on each instance
379
+ // eslint-disable-next-line no-param-reassign
380
+ options.individualHooks = true;
381
+ };
382
+ exports.beforeBulkCreate = beforeBulkCreate;
383
+ /**
384
+ * Hook to enable individual hooks for bulk update operations
385
+ */
386
+ const beforeBulkUpdate = (options) => {
387
+ // This will activate the beforeUpdate hook on each instance
388
+ // eslint-disable-next-line no-param-reassign
389
+ options.individualHooks = true;
390
+ };
391
+ exports.beforeBulkUpdate = beforeBulkUpdate;
@@ -0,0 +1,5 @@
1
+ import enrichResults from './enrich';
2
+ import { beforeFind } from './find';
3
+ import workaround from './workaround';
4
+ import { beforeCreate, beforeUpdate, beforeBulkCreate, beforeBulkUpdate } from './hooks';
5
+ export { enrichResults, beforeFind, workaround, beforeCreate, beforeUpdate, beforeBulkCreate, beforeBulkUpdate, };
@@ -1 +1,17 @@
1
- import e from"./enrich.js";import{beforeFind as t}from"./find.js";import{beforeBulkCreate as n,beforeBulkUpdate as r,beforeCreate as i,beforeUpdate as a}from"./hooks.js";export{};
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.beforeBulkUpdate = exports.beforeBulkCreate = exports.beforeUpdate = exports.beforeCreate = exports.workaround = exports.beforeFind = exports.enrichResults = void 0;
7
+ const enrich_1 = __importDefault(require("./enrich"));
8
+ exports.enrichResults = enrich_1.default;
9
+ const find_1 = require("./find");
10
+ Object.defineProperty(exports, "beforeFind", { enumerable: true, get: function () { return find_1.beforeFind; } });
11
+ const workaround_1 = __importDefault(require("./workaround"));
12
+ exports.workaround = workaround_1.default;
13
+ const hooks_1 = require("./hooks");
14
+ Object.defineProperty(exports, "beforeCreate", { enumerable: true, get: function () { return hooks_1.beforeCreate; } });
15
+ Object.defineProperty(exports, "beforeUpdate", { enumerable: true, get: function () { return hooks_1.beforeUpdate; } });
16
+ Object.defineProperty(exports, "beforeBulkCreate", { enumerable: true, get: function () { return hooks_1.beforeBulkCreate; } });
17
+ Object.defineProperty(exports, "beforeBulkUpdate", { enumerable: true, get: function () { return hooks_1.beforeBulkUpdate; } });
@@ -0,0 +1,10 @@
1
+ import type { CustomFieldOptions, ModelOptions } from '../types';
2
+ /**
3
+ * A hook to update the custom fields when updating a model (more then one instance).
4
+ */
5
+ export declare const beforeBulkUpdate: (options: any) => void;
6
+ /**
7
+ * A hook to update the custom fields when updating a model instance.
8
+ * TODO - cleanup if update fail
9
+ */
10
+ export declare const beforeUpdate: (scopeAttributes: string[], modelOptions?: ModelOptions, sadotOptions?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>) => (instance: any, options: any) => Promise<void>;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.beforeUpdate = exports.beforeBulkUpdate = void 0;
7
+ const logger_1 = __importDefault(require("../utils/logger"));
8
+ const scopeAttributes_1 = __importDefault(require("../utils/scopeAttributes"));
9
+ const updateInstanceValues_1 = __importDefault(require("./utils/updateInstanceValues"));
10
+ /**
11
+ * A hook to update the custom fields when updating a model (more then one instance).
12
+ */
13
+ const beforeBulkUpdate = (options) => {
14
+ // This will activate the beforeUpdate hook on each updating instance.
15
+ // eslint-disable-next-line no-param-reassign
16
+ options.individualHooks = true;
17
+ };
18
+ exports.beforeBulkUpdate = beforeBulkUpdate;
19
+ /**
20
+ * A hook to update the custom fields when updating a model instance.
21
+ * TODO - cleanup if update fail
22
+ */
23
+ const beforeUpdate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instance, options) => {
24
+ logger_1.default.debug('sadot - before update hook');
25
+ const { fields } = options;
26
+ const modelType = instance.constructor.name;
27
+ const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
28
+ const customFieldsIdx = fields.indexOf('customFields');
29
+ if (customFieldsIdx > -1) {
30
+ const { customFields } = instance;
31
+ if (!Object.keys(customFields).length) {
32
+ return;
33
+ }
34
+ await (0, updateInstanceValues_1.default)({
35
+ modelId: instance.id,
36
+ modelType,
37
+ identifiers,
38
+ customFields,
39
+ options: {
40
+ useCustomFieldsEntries: sadotOptions.useCustomFieldsEntries,
41
+ transaction: options.transaction,
42
+ modelOptions,
43
+ },
44
+ });
45
+ // eslint-disable-next-line no-param-reassign
46
+ fields.splice(customFieldsIdx, 1);
47
+ }
48
+ };
49
+ exports.beforeUpdate = beforeUpdate;
@@ -0,0 +1,15 @@
1
+ import type { Transaction } from 'sequelize';
2
+ import type { ModelOptions } from '../../types';
3
+ interface UpdateInstanceValuesParams {
4
+ modelId: string;
5
+ modelType: string;
6
+ identifiers: string[];
7
+ customFields: Record<string, any>;
8
+ options?: {
9
+ transaction?: Transaction;
10
+ modelOptions?: ModelOptions;
11
+ useCustomFieldsEntries?: boolean;
12
+ };
13
+ }
14
+ declare const updateInstanceValues: ({ modelId, modelType, identifiers, customFields, options, }: UpdateInstanceValuesParams) => Promise<void>;
15
+ export default updateInstanceValues;
@@ -1,2 +1,50 @@
1
- import{updateValues as e}from"../../repository/value.js";import{findEntriesByModelId as t,updateEntries as n}from"../../repository/entries.js";var r=async({modelId:r,modelType:i,identifiers:a,customFields:o,options:s={modelOptions:{},useCustomFieldsEntries:!1}})=>{if(await e(i,r,a,o,{...s,modelOptions:s.modelOptions??{}}),!s?.useCustomFieldsEntries)return;let{dataValues:{customFields:c}}=await t(r,s)??{dataValues:{}};await n(r,i,{...c,...o},a,{...s,modelOptions:s.modelOptions??{}})};export{r as default};
2
- //# sourceMappingURL=updateInstanceValues.js.map
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const ValueRepo = __importStar(require("../../repository/value"));
27
+ const EntriesRepo = __importStar(require("../../repository/entries"));
28
+ const updateInstanceValues = async ({ modelId, modelType, identifiers, customFields, options = {
29
+ modelOptions: {},
30
+ useCustomFieldsEntries: false,
31
+ }, }) => {
32
+ await ValueRepo.updateValues(modelType, modelId, identifiers, customFields, {
33
+ ...options,
34
+ modelOptions: options.modelOptions ?? {},
35
+ });
36
+ /*
37
+ T.Y TODO - Once we're ready to switch from custom_field_values to custom_field_entries, we should remove the ValueRepo.updateValues call.
38
+ Currently, We're updating both tables to keep the data in sync, but not all microservices are using the new table yet.
39
+ */
40
+ if (!options?.useCustomFieldsEntries) {
41
+ return;
42
+ }
43
+ const { dataValues: { customFields: oldCustomFields } } = await EntriesRepo.findEntriesByModelId(modelId, options) ?? { dataValues: {} };
44
+ const newCustomFields = { ...oldCustomFields, ...customFields };
45
+ await EntriesRepo.updateEntries(modelId, modelType, newCustomFields, identifiers, {
46
+ ...options,
47
+ modelOptions: options.modelOptions ?? {},
48
+ });
49
+ };
50
+ exports.default = updateInstanceValues;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Workaround to a bug in sequelize.🐛
3
+ *
4
+ * **afterFind hook** isn't working on nested (included) models.
5
+ * The solution here is to add a global afterFind hook,
6
+ * which manually calls the afterFind hook of each model, recursively
7
+ * https://github.com/sequelize/sequelize/issues/4627
8
+ */
9
+ declare const handleChildrenAfterFindHook: (instances: any, options: any, level?: number) => any;
10
+ export default handleChildrenAfterFindHook;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /**
3
+ * Workaround to a bug in sequelize.🐛
4
+ *
5
+ * **afterFind hook** isn't working on nested (included) models.
6
+ * The solution here is to add a global afterFind hook,
7
+ * which manually calls the afterFind hook of each model, recursively
8
+ * https://github.com/sequelize/sequelize/issues/4627
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ const handleChildrenAfterFindHook = async (instances, options, level = 0) => {
12
+ if (!instances)
13
+ return Promise.resolve();
14
+ if (Array.isArray(instances)) {
15
+ return Promise.all(instances.map((instance) => {
16
+ const { options: instanceOptions } = instance.constructor;
17
+ return handleChildrenAfterFindHook(instance, instanceOptions, level);
18
+ }));
19
+ }
20
+ const instance = instances;
21
+ const { constructor } = instance;
22
+ /**
23
+ * Root model will have already run their "afterFind" hook.
24
+ * Only run children "afterFind" hooks.
25
+ */
26
+ if (level >= 1) {
27
+ await constructor.runHooks('afterFind', instance, options);
28
+ }
29
+ const { associations } = constructor;
30
+ const associatedNames = Object.keys(instance).filter((attribute) => Object.keys(associations).includes(attribute));
31
+ if (associatedNames.length) {
32
+ const childInstances = associatedNames.map((name) => instance[name]);
33
+ return handleChildrenAfterFindHook(childInstances, options, level + 1);
34
+ }
35
+ return Promise.resolve();
36
+ };
37
+ exports.default = handleChildrenAfterFindHook;
package/dist/index.d.ts CHANGED
@@ -1,23 +1,13 @@
1
- import { CUSTOM_FIELDS_FILTER_SCOPE, CustomFieldDefinitionType, supportedEntities } from "./utils/constants/index.js";
2
- import { CustomFieldValue } from "./models/CustomFieldValue.js";
3
- import { CustomFieldEntries } from "./models/CustomFieldEntries.js";
4
- import { CustomValidator } from "./models/CustomValidator.js";
5
- import "./models/index.js";
6
- import { CustomFieldDefinition } from "./models/CustomFieldDefinition.js";
7
- import { CustomFieldOptions, ModelFetcher, Models } from "./types/index.js";
8
- import { CustomFieldsSchema } from "./utils/validations/schema/custom-fields.js";
9
- import { generateCustomFieldSearchQueryPayload, generateRandomString } from "./utils/helpers/index.js";
10
- import { customFieldsSortScope } from "./scopes/filter.js";
11
- import { Sequelize } from "sequelize-typescript";
12
- import { Application } from "express";
13
-
14
- //#region src/index.d.ts
1
+ import type { Application } from 'express';
2
+ import type { Sequelize } from 'sequelize-typescript';
3
+ import type { CustomFieldOptions, ModelFetcher, Models } from './types';
4
+ export * from './utils/validations/schema/custom-fields';
5
+ export * from './utils/constants';
6
+ export * from './utils/helpers';
15
7
  /**
16
- * Adding custom fields enrichment to the models inside the MODELS_FILE_NAME json file
17
- * @see {@link 'custom-fields/config'} for configurations
18
- */
19
- declare const useCustomFields: (app: Pick<Application, "use"> | null, getModel: ModelFetcher, options: CustomFieldOptions) => Promise<Sequelize>;
20
- declare const disableCustomFields: (models: Models[], getModel: ModelFetcher) => void;
21
- //#endregion
22
- export { CUSTOM_FIELDS_FILTER_SCOPE, CustomFieldDefinition, CustomFieldDefinitionType, CustomFieldEntries, CustomFieldValue, CustomFieldsSchema, CustomValidator, customFieldsSortScope, useCustomFields as default, disableCustomFields, generateCustomFieldSearchQueryPayload, generateRandomString, supportedEntities };
23
- //# sourceMappingURL=index.d.ts.map
8
+ * Adding custom fields enrichment to the models inside the MODELS_FILE_NAME json file
9
+ * @see {@link 'custom-fields/config'} for configurations
10
+ */
11
+ declare const useCustomFields: (app: Application | null, getModel: ModelFetcher, options: CustomFieldOptions) => Promise<Sequelize>;
12
+ export default useCustomFields;
13
+ export declare const disableCustomFields: (models: Models[], getModel: ModelFetcher) => void;