@autofleet/sadot 1.1.7-beta → 1.1.8

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.103.0/helpers/decorate.cjs +1 -0
  2. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/decorate.js +1 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.103.0/helpers/decorateMetadata.cjs +1 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.103.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 -388
  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 -69
  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 -112
  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 -28
  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 -479
  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 -119
  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 -122
  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,116 +0,0 @@
1
- import type { FindOptions, WhereOptions } from 'sequelize';
2
- import { CustomFieldValue, CustomFieldDefinition } from '../models';
3
- import * as DefinitionRepo from './definition';
4
- import type { CreateCustomFieldValue, ValuesToUpdate } from '../types/value';
5
- import logger from '../utils/logger';
6
- import { MissingDefinitionError } from '../errors';
7
- import type { ModelOptions } from '../types';
8
- import { formatFunctions } from './utils/formatValues';
9
-
10
- export const findByModelIdAndDefinition = async (modelId: string, customFieldDefinitionId: string) =>
11
- CustomFieldValue.findAll({ where: { modelId, customFieldDefinitionId }, include: [CustomFieldDefinition] });
12
-
13
- export const create = async (data: CreateCustomFieldValue, withAssociations = false) => {
14
- const created = await CustomFieldValue.create(data);
15
- if (withAssociations) {
16
- const createdWithAssociations = await findByModelIdAndDefinition(created.modelId, created.customFieldDefinitionId);
17
- return createdWithAssociations?.[0];
18
- }
19
- return created;
20
- };
21
-
22
- export const findAllValues = async () => CustomFieldValue.findAll({ include: [CustomFieldDefinition] });
23
- /**
24
- * Get all values for model instance id (with their definitions)
25
- * @param modelId
26
- * @returns CustomFieldValue[]
27
- */
28
- export const findValuesByModelId = async (modelId: string) => CustomFieldValue.findAll({ where: { modelId }, include: [CustomFieldDefinition] });
29
-
30
- /**
31
- * Retrieves custom field values for given model IDs
32
- * @param modelIds - An array of model IDs to query custom field values for.
33
- * @param options - Optional configuration object.
34
- */
35
- export const findValuesByModelIds = async (modelIds: string[], options?): Promise<CustomFieldValue[]> => {
36
- const { transaction } = options;
37
- return CustomFieldValue.findAll({
38
- where: { modelId: modelIds },
39
- transaction,
40
- raw: true,
41
- nest: true,
42
- });
43
- };
44
-
45
- /**
46
- * Try to update custom field values for a model instance.
47
- * Create new value record if not exists, but fails if value's definition not exist.
48
- * Return the updated values
49
- */
50
- export const updateValues = async (
51
- modelType: string,
52
- modelId: string,
53
- identifiers: string[],
54
- valuesToUpdate: ValuesToUpdate,
55
- options: FindOptions & { modelOptions?: ModelOptions } = {},
56
- ): Promise<CustomFieldValue[]> => {
57
- const names = Object.keys(valuesToUpdate);
58
- logger.debug(`custom-fields: updating values for ${modelType} ${modelId}`, {
59
- names,
60
- optionsKeys: options ? Object.keys(options) : null,
61
- valuesToUpdate,
62
- identifiers,
63
- });
64
- const { modelOptions, transaction } = options;
65
-
66
- const where: WhereOptions = {
67
- modelType,
68
- name: names,
69
- ...(!options.modelOptions?.useEntityIdFromInclude && { entityId: identifiers }),
70
- };
71
-
72
- const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true, transaction, include: modelOptions.include?.(identifiers) }) ?? [];
73
-
74
- const disabledDefinitions = fieldDefinitions.filter((def) => def.disabled);
75
- if (fieldDefinitions.length !== names.length) {
76
- logger.warn(`custom-fields: missing definitions for ${modelType} ${modelId}`, { names, fieldDefinitions });
77
- const missingDefinitions = names.filter((name) => !fieldDefinitions.some((def) => def.name === name));
78
- throw new MissingDefinitionError(missingDefinitions);
79
- }
80
-
81
- const disabledNames = disabledDefinitions?.map((def) => def.name) || [];
82
- const valuesWithDisabledDefinitions = names.filter((name) => disabledNames.includes(name));
83
- if (valuesWithDisabledDefinitions?.length > 0) {
84
- logger.warn(`custom-fields: trying to update disabled values: ${valuesWithDisabledDefinitions.join(', ')}`);
85
- }
86
-
87
- const values: CreateCustomFieldValue[] = names.map((name) => {
88
- const fieldDefinition = fieldDefinitions.find((def) => def.name === name);
89
- const formatFunction = formatFunctions[fieldDefinition.fieldType];
90
- const value = formatFunction ? formatFunction(valuesToUpdate[name]) : valuesToUpdate[name];
91
- return {
92
- modelId,
93
- updatedAt: new Date(),
94
- customFieldDefinitionId: fieldDefinition.id,
95
- value: value !== undefined ? value : fieldDefinition.defaultValue,
96
- };
97
- });
98
-
99
- return Promise.all(values.map(async (value) => {
100
- const [cfv] = await CustomFieldValue.upsert(value, {
101
- transaction: options.transaction,
102
- });
103
- return cfv;
104
- }));
105
- };
106
-
107
- export const deleteValue = (
108
- id: string,
109
- options: any = {},
110
- ): Promise<any> => CustomFieldValue.update(
111
- { deletedAt: new Date() },
112
- {
113
- where: { id },
114
- transaction: options.transaction,
115
- },
116
- );
@@ -1,100 +0,0 @@
1
- /* eslint-disable import/prefer-default-export */
2
- import { Op } from 'sequelize';
3
- import { Sequelize } from 'sequelize-typescript';
4
- import { customFields } from '@autofleet/common-types';
5
- import { generateRandomString } from '../utils/helpers';
6
- import type { CustomFieldOptions } from '../types';
7
- import {
8
- formatConditionsForEntries,
9
- formatConditionsForValues,
10
- getFilterCustomFieldsSubQuery,
11
- getSortCustomFieldsSubQuery,
12
- SubQueryType,
13
- type ConditionValue,
14
- type CustomFieldFilterOptions,
15
- } from './helpers/filter.helpers';
16
-
17
- const { CUSTOM_FIELDS_FILTER_SCOPE } = customFields;
18
-
19
- type customFieldsFilterScopeParams = {
20
- replacementsMap: Record<string, string>;
21
- scopeValue: Record<string, ConditionValue>;
22
- }
23
-
24
- /**
25
- * A Sequelize scope for filtering models by custom fields.
26
- * This scope builds a WHERE clause to be applied on the main query.
27
- *
28
- * @param name - The model type name used to join custom_field_definitions.
29
- * @returns A function that takes conditions and returns the Sequelize options object.
30
- */
31
- export const customFieldsFilterScope = (
32
- name: string,
33
- options?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>,
34
- ) => ({ replacementsMap: replacements, scopeValue: conditions }: customFieldsFilterScopeParams): CustomFieldFilterOptions => {
35
- if (!conditions || Object.keys(conditions).length === 0) {
36
- return {};
37
- }
38
-
39
- const queryType = options?.useCustomFieldsEntries ? SubQueryType.ENTRIES : SubQueryType.VALUES;
40
- const reverseReplacementsMap = new Map(Object.entries(replacements).map(([key, value]) => [value, key]));
41
- // Build the WHERE clause for custom field filtering
42
- const conditionsStrings = Object.entries(conditions).map(([key, condition]) => {
43
- switch (queryType) {
44
- case SubQueryType.ENTRIES:
45
- return formatConditionsForEntries(key, condition, reverseReplacementsMap);
46
- case SubQueryType.VALUES:
47
- return formatConditionsForValues(key, condition, reverseReplacementsMap);
48
- default:
49
- return false;
50
- }
51
- }).filter(Boolean);
52
- if (conditionsStrings.length === 0) {
53
- return {};
54
- }
55
- const subQuery = getFilterCustomFieldsSubQuery(queryType, name, conditionsStrings);
56
-
57
- return {
58
- where: {
59
- id: {
60
- [Op.in]: Sequelize.literal(`(${subQuery})`),
61
- },
62
- },
63
- replacements,
64
- };
65
- };
66
-
67
- export const scopeName = CUSTOM_FIELDS_FILTER_SCOPE;
68
-
69
- export const customFieldsSortScope = (
70
- name: string,
71
- options?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>,
72
- ) => ({ replacementsMap, scopeValue: sort }) => {
73
- if (!sort || sort.length === 0) {
74
- return {};
75
- }
76
-
77
- const queryType = options?.useCustomFieldsEntries ? SubQueryType.ENTRIES : SubQueryType.VALUES;
78
- const randomStr = generateRandomString();
79
- const includes = Object.entries(sort).map(([key]) => {
80
- const replacementKey = Object.keys(replacementsMap).find(
81
- (randomString) => replacementsMap[randomString] === key,
82
- );
83
- return ([
84
- Sequelize.literal(getSortCustomFieldsSubQuery(queryType, name, replacementKey)),
85
- randomStr,
86
- ]);
87
- });
88
-
89
- const orders = Object.entries(sort).map(([, sortObject]) => {
90
- const direction = typeof sortObject === 'string' ? sortObject : Object.values(sortObject)[0];
91
- return Sequelize.literal(`"${randomStr}" ${direction || 'ASC'}`);
92
- });
93
- return {
94
- attributes: {
95
- include: includes,
96
- },
97
- order: orders,
98
- replacements: replacementsMap,
99
- };
100
- };
@@ -1,227 +0,0 @@
1
- import type { WhereOptions } from 'sequelize';
2
-
3
- /**
4
- * Type representing possible condition values.
5
- * Currently supporting strings and arrays of strings.
6
- * More types to be added (TBA).
7
- */
8
- export type ConditionWithOperator = {
9
- operator: string;
10
- value: string;
11
- };
12
- export type ConditionValue = ConditionWithOperator | ConditionWithOperator[] | string | string[];
13
-
14
- export type CustomFieldSort = {
15
- field: string;
16
- direction: 'ASC' | 'DESC';
17
- }
18
-
19
- export type CustomFieldFilterOptions = {
20
- where?: WhereOptions;
21
- replacements?: Record<string, string>;
22
- }
23
-
24
- export enum SubQueryType {
25
- VALUES = 'values',
26
- ENTRIES = 'entries',
27
- }
28
-
29
- export const isConditionStringArray = (input: any): input is string[] => Array.isArray(input) && typeof input[0] === 'string';
30
- export const isBooleanString = (input: string): boolean => ['true', 'false'].includes(input.toString());
31
- export const isDate = (input: any): input is Date => input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
32
-
33
- export const castValueToJsonb = (value: string, type: string) => `to_jsonb(${value}::${type})`;
34
- export const castValueToJsonbText = (value: string) => castValueToJsonb(value, 'text');
35
- export const castValueToJsonbBoolean = (value: string) => castValueToJsonb(value, 'boolean');
36
- export const castValueToJsonbNumeric = (value: string) => castValueToJsonb(value, 'numeric');
37
- export const castIfNeeded = (columnName: string, conditionValue: string): string => {
38
- if (isDate(conditionValue)) {
39
- return castValueToJsonb(columnName, 'timestamp');
40
- }
41
- return columnName;
42
- };
43
-
44
- export const AND_DELIMITER = ' AND ';
45
- export const OR_DELIMITER = ' OR ';
46
- export const CD_TABLE_ALIAS = 'cd';
47
- export const CD_NAME_COLUMN = `${CD_TABLE_ALIAS}.name`;
48
- export const CV_TABLE_ALIAS = 'cv';
49
- export const CV_VALUE_COLUMN = `${CV_TABLE_ALIAS}.value`;
50
- export const CE_TABLE_ALIAS = 'ce';
51
-
52
- const getSingleConditionWithOperator = (value: any, operator: string, replacementKey: string, reverseReplacementsMap: Map<string, string>) => {
53
- let type = 'text';
54
- if (isDate(value)) {
55
- type = 'date';
56
- } else if (!Number.isNaN(Number(value))) {
57
- type = 'numeric';
58
- } else if (isBooleanString(value)) {
59
- type = 'boolean';
60
- }
61
- const replacedValue = reverseReplacementsMap.get(value);
62
-
63
- return `(jsonb_extract_path_text(${CE_TABLE_ALIAS}.custom_fields, :${replacementKey})::${type}) ${operator} :${replacedValue}`;
64
- };
65
-
66
- const getFormattedValue = (value: string) => {
67
- let formattedValue: string | number | boolean = value;
68
- if (isBooleanString(value)) {
69
- formattedValue = value === 'true';
70
- } else if (!Number.isNaN(Number(value))) {
71
- formattedValue = Number(value);
72
- }
73
-
74
- return formattedValue;
75
- };
76
-
77
- const getJSONSubQuery = (value: string, key: string) => {
78
- const formattedValue = getFormattedValue(value);
79
- const jsonQuery = JSON.stringify({ [key]: formattedValue });
80
- let jsonQueryWithStringBoolean;
81
- if (isBooleanString(value)) {
82
- jsonQueryWithStringBoolean = `${CE_TABLE_ALIAS}.custom_fields @> '${JSON.stringify({ [key]: value })}'`;
83
- }
84
- return `
85
- (
86
- ${jsonQueryWithStringBoolean ? `${jsonQueryWithStringBoolean} OR` : ''}
87
- ${CE_TABLE_ALIAS}.custom_fields @> '${jsonQuery}'
88
- )
89
- `;
90
- };
91
-
92
- export const getFilterCustomFieldsSubQuery = (queryType: SubQueryType, modelType: string, conditionsStrings: Array<string | boolean>): string => {
93
- switch (queryType) {
94
- case SubQueryType.VALUES:
95
- return `
96
- SELECT ${CV_TABLE_ALIAS}.model_id
97
- FROM custom_field_values AS ${CV_TABLE_ALIAS}
98
- INNER JOIN custom_field_definitions AS ${CD_TABLE_ALIAS} ON ${CV_TABLE_ALIAS}.custom_field_definition_id = ${CD_TABLE_ALIAS}.id
99
- ${AND_DELIMITER}${CD_TABLE_ALIAS}.model_type = '${modelType}'
100
- WHERE ${conditionsStrings.join(OR_DELIMITER)}
101
- ${AND_DELIMITER}${CV_TABLE_ALIAS}.deleted_at IS NULL${AND_DELIMITER}${CD_TABLE_ALIAS}.deleted_at IS NULL
102
- GROUP BY ${CV_TABLE_ALIAS}.model_id
103
- HAVING COUNT(DISTINCT ${CV_TABLE_ALIAS}.custom_field_definition_id) = ${conditionsStrings.length}
104
- `.replace(/\n/g, '');
105
- case SubQueryType.ENTRIES:
106
- return `
107
- SELECT ce.model_id
108
- FROM custom_field_entries ce
109
- JOIN custom_field_definitions cfd
110
- ON ce.model_type = cfd.model_type
111
- AND ce.entity_id = cfd.entity_id
112
- WHERE
113
- cfd.deleted_at IS NULL AND
114
- ${conditionsStrings.join(AND_DELIMITER)}
115
- `;
116
- default:
117
- throw new Error('Invalid query type');
118
- }
119
- };
120
-
121
- export const getSortCustomFieldsSubQuery = (queryType: SubQueryType, modelType: string, replacementKey: string): string => {
122
- switch (queryType) {
123
- case SubQueryType.VALUES:
124
- return `(
125
- SELECT value
126
- FROM (SELECT cv.model_id, cv.value
127
- FROM custom_field_values AS cv INNER JOIN custom_field_definitions AS cd
128
- ON cv.custom_field_definition_id = cd.id
129
- ${AND_DELIMITER}cd.model_type = '${modelType}'
130
- WHERE cv.model_id = "${modelType}"."id"
131
- ${AND_DELIMITER}cd.name = :${replacementKey}
132
- ) AS CustomFieldAggregation
133
- )
134
- `;
135
- case SubQueryType.ENTRIES:
136
- return `(
137
- SELECT
138
- customFields.value
139
- FROM
140
- custom_field_entries AS ${CE_TABLE_ALIAS},
141
- jsonb_each_text(custom_fields) AS customFields
142
- WHERE
143
- customFields.key = :${replacementKey}${AND_DELIMITER}
144
- ${CE_TABLE_ALIAS}.model_type = '${modelType}'${AND_DELIMITER}
145
- ${CE_TABLE_ALIAS}.model_id = "${modelType}"."id"
146
- )
147
- `;
148
- default:
149
- throw new Error('Invalid query type');
150
- }
151
- };
152
-
153
- export const formatConditionsForValues = (key: string, condition: ConditionValue, reverseReplacementsMap: Map<string, string>) => {
154
- const replacementKey = reverseReplacementsMap.get(key);
155
- if (!replacementKey) {
156
- return false;
157
- }
158
-
159
- const columnCondition = `(${CD_NAME_COLUMN} = :${replacementKey})`;
160
- if (Array.isArray(condition)) {
161
- if (condition.length === 0) {
162
- // if empty array, the condition is ignored
163
- return false;
164
- }
165
-
166
- if (isConditionStringArray(condition)) {
167
- const values = condition.flatMap((v) => {
168
- const valRandom = reverseReplacementsMap.get(v);
169
- if (isBooleanString(v)) {
170
- return [castValueToJsonbText(`:${valRandom}`), castValueToJsonbBoolean(`:${valRandom}`)];
171
- }
172
- if (!Number.isNaN(Number(v))) {
173
- return castValueToJsonbNumeric(`:${valRandom}`);
174
- }
175
- return castValueToJsonbText(`:${valRandom}`);
176
- }).join(',');
177
- return `(${columnCondition}${AND_DELIMITER}${CV_VALUE_COLUMN} IN (${values}))`;
178
- }
179
- return condition.map((c) => {
180
- const valRep = reverseReplacementsMap.get(c.value);
181
- const valueAsJsonb = castValueToJsonbText(`:${valRep}`);
182
-
183
- return `(${columnCondition}${AND_DELIMITER}${castIfNeeded(CV_VALUE_COLUMN, c.value)} ${c.operator} ${valueAsJsonb})`;
184
- }).join(AND_DELIMITER);
185
- }
186
- if (typeof condition === 'string' || typeof condition === 'number') {
187
- const conditionRep = reverseReplacementsMap.get(condition);
188
- const valueAsJsonb = !Number.isNaN(Number(condition)) ? castValueToJsonbNumeric(`:${conditionRep}`) : castValueToJsonbText(`:${conditionRep}`);
189
- const valueAsJsonbBoolean = isBooleanString(condition) ? `${OR_DELIMITER}${CV_VALUE_COLUMN} = ${castValueToJsonbBoolean(`:${conditionRep}`)}` : '';
190
- return `(${columnCondition}${AND_DELIMITER}(${castIfNeeded(CV_VALUE_COLUMN, condition)} = ${valueAsJsonb}${valueAsJsonbBoolean}))`;
191
- }
192
- if (condition?.operator) {
193
- const valueRep = reverseReplacementsMap.get(condition.value);
194
- const valueAsJsonb = castValueToJsonbText(`:${valueRep}`);
195
- return `( ${columnCondition}${AND_DELIMITER}${castIfNeeded(CV_VALUE_COLUMN, condition.value)} ${condition.operator} ${valueAsJsonb})`;
196
- }
197
- return false;
198
- };
199
-
200
- export const formatConditionsForEntries = (key: string, condition: ConditionValue, reverseReplacementsMap: Map<string, string>) => {
201
- const replacementKey = reverseReplacementsMap.get(key);
202
- if (!replacementKey) {
203
- return false;
204
- }
205
-
206
- if (Array.isArray(condition)) {
207
- if (condition.length === 0) {
208
- // if empty array, the condition is ignored
209
- return false;
210
- }
211
-
212
- if (isConditionStringArray(condition)) {
213
- const values = condition.map((value) => getJSONSubQuery(value, key)).join(`${OR_DELIMITER}\n`);
214
- return `( ${values})`;
215
- }
216
- return condition.map((c) => getSingleConditionWithOperator(c.value, c.operator, replacementKey, reverseReplacementsMap)).join(AND_DELIMITER);
217
- }
218
-
219
- if (typeof condition === 'string' || typeof condition === 'number') {
220
- return getJSONSubQuery(condition, key);
221
- }
222
-
223
- if (condition?.operator) {
224
- return getSingleConditionWithOperator(condition.value, condition.operator, replacementKey, reverseReplacementsMap);
225
- }
226
- return false;
227
- };
@@ -1,6 +0,0 @@
1
- /* eslint-disable import/prefer-default-export */
2
- import { customFieldsFilterScope } from './filter';
3
-
4
- export {
5
- customFieldsFilterScope,
6
- };
@@ -1,40 +0,0 @@
1
- import express from 'express';
2
- import { Router } from '@autofleet/node-common';
3
- import logger from '../../utils/logger';
4
- import { TestModel } from '../../models';
5
-
6
- const app = express();
7
- app.use(express.json());
8
- const api = Router({ logger });
9
-
10
- api.get('/v1/test-models', async (req, res) => {
11
- const testModels = await TestModel.findAll();
12
- return res.json(testModels);
13
- });
14
-
15
- api.get('/v1/test-models/:testModelId', async (req, res) => {
16
- const { params: { testModelId } } = req;
17
- const testModel = await TestModel.findByPk(testModelId);
18
- return res.json(testModel);
19
- });
20
-
21
- api.post('/v1/test-models', async (req, res) => {
22
- const { body } = req;
23
- const testModel = await TestModel.create(body);
24
- return res.json(testModel);
25
- });
26
-
27
- api.patch('/v1/test-models/:testModelId', async (req, res) => {
28
- const { body, params: { testModelId } } = req;
29
- const testModel = await TestModel.update(body, {
30
- where: {
31
- id: testModelId,
32
- },
33
- returning: true,
34
- });
35
- return res.json(testModel[1][0]);
36
- });
37
-
38
- app.use('/api', api);
39
-
40
- export default app;
@@ -1,39 +0,0 @@
1
- import { generateCustomFieldSearchQueryPayload } from '../../../index';
2
- import * as DefinitionRepo from '../../../repository/definition';
3
- import { createDefinition } from '../../mocks/definition.mock';
4
- import { createTestModels } from '../../mocks/testModel';
5
- import { TestModel } from '../../../models';
6
-
7
- interface CustomFieldsSearchTestFlowInput {
8
- fieldType: string;
9
- fieldValue: string | number;
10
- searchTerm: string;
11
- expectedNumberOfQueryResults: number;
12
- }
13
-
14
- const customFieldsSearchTestFlow = async ({
15
- fieldType,
16
- fieldValue,
17
- searchTerm,
18
- expectedNumberOfQueryResults,
19
- }: CustomFieldsSearchTestFlowInput): Promise<void> => {
20
- const definition = createDefinition({ fieldType, name: 'coolDefinition' });
21
- await DefinitionRepo.create({ ...definition });
22
- const [testModel1] = await createTestModels(definition.entityId, 2);
23
- await testModel1.update({ customFields: { [definition.name]: fieldValue } });
24
- const models = await TestModel.findAndCountAll(
25
- {
26
- ...generateCustomFieldSearchQueryPayload(
27
- searchTerm,
28
- TestModel,
29
- definition.entityId,
30
- ),
31
- },
32
- );
33
- expect(models.count).toBe(expectedNumberOfQueryResults);
34
- if (expectedNumberOfQueryResults > 0) {
35
- expect(models.rows[0].dataValues.id).toBe(testModel1.id);
36
- }
37
- };
38
-
39
- export default customFieldsSearchTestFlow;
@@ -1,43 +0,0 @@
1
- import type { Application } from 'express';
2
- import type { Sequelize } from 'sequelize-typescript';
3
- import useCustomFields from '../..';
4
- import { cleanup, getModel } from '.';
5
- import databaseConfig from './database-config';
6
- import initDB, { createSequelizeMeta } from '../../utils/db';
7
- import type { Models } from '../../types';
8
-
9
- export function commonTestHooks(
10
- app: Application | null = null,
11
- models: Models[] = [{ name: 'TestModel', scopeAttributes: ['fleetId'] }],
12
- options: { useCustomFieldsEntries: boolean, useValidators?: boolean } = {
13
- useCustomFieldsEntries: false,
14
- useValidators: false,
15
- },
16
- ) {
17
- let sequelize: Sequelize;
18
-
19
- beforeAll(async () => {
20
- sequelize = initDB(databaseConfig);
21
- await createSequelizeMeta(sequelize);
22
- await useCustomFields(app, getModel, {
23
- models,
24
- databaseConfig,
25
- getUser: () => undefined,
26
- sequelize,
27
- useCustomFieldsEntries: options.useCustomFieldsEntries,
28
- useValidators: options.useValidators,
29
- });
30
- });
31
-
32
- afterEach(async () => {
33
- jest.clearAllMocks();
34
- await cleanup({
35
- useCustomFieldsEntries: options.useCustomFieldsEntries,
36
- useValidators: options.useValidators,
37
- });
38
- });
39
-
40
- afterAll(async () => {
41
- await sequelize.close();
42
- });
43
- }
@@ -1,15 +0,0 @@
1
- export default {
2
- test: {
3
- username: process.env.DB_USERNAME || '',
4
- password: process.env.DB_PASSWORD || null,
5
- database: process.env.DB_NAME || 'postgres',
6
- host: process.env.DB_HOST || '127.0.0.1',
7
- port: process.env.DB_PORT || 5432,
8
- dialect: process.env.DB_TYPE || 'postgres',
9
- define: {
10
- underscored: true,
11
- underscoredAll: true,
12
- },
13
- logging: false,
14
- },
15
- };
@@ -1,35 +0,0 @@
1
- import { generateFilterReplacements } from '@autofleet/sheilta';
2
- import {
3
- ContextAwareTestModel, ContextTestModel, CustomFieldDefinition, CustomFieldEntries, CustomValidator, TestModel,
4
- } from '../../models';
5
- import type { CustomFieldOptions } from '../../types';
6
-
7
- // eslint-disable-next-line import/prefer-default-export
8
- export const cleanup = async (options?: Pick<CustomFieldOptions, 'useCustomFieldsEntries' | 'useValidators'>): Promise<void> => {
9
- if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') {
10
- await CustomFieldDefinition.unscoped().destroy({ where: {} });
11
- await TestModel.destroy({ where: {} });
12
- await ContextAwareTestModel.destroy({ where: {} });
13
- await ContextTestModel.destroy({ where: {} });
14
-
15
- if (options?.useCustomFieldsEntries) {
16
- await CustomFieldEntries.unscoped().destroy({ where: {} });
17
- }
18
-
19
- // Clean up validators if they were used
20
- if (options?.useValidators) {
21
- await CustomValidator.unscoped().destroy({ where: {} });
22
- }
23
- }
24
- };
25
-
26
- export const getModel = (name: string) => {
27
- // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires
28
- const models = require('../../models');
29
- return models[name];
30
- };
31
-
32
- export const getReplacementMapWithScopeValue = (conditions: Record<string, any>) => ({
33
- replacementsMap: generateFilterReplacements(Object.fromEntries(Object.entries(conditions).map(([key, value]) => [`customFields.${key}`, value]))),
34
- scopeValue: conditions,
35
- });