@autofleet/sadot 1.1.2-beta → 1.1.2

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