@autofleet/sadot 0.0.1-beta → 0.0.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/{src/api → api}/index.js +1 -0
  2. package/dist/api/index.js.map +1 -0
  3. package/dist/{src/api → api}/v1/definition/index.js +28 -25
  4. package/dist/api/v1/definition/index.js.map +1 -0
  5. package/dist/api/v1/definition/validations.js +36 -0
  6. package/dist/api/v1/definition/validations.js.map +1 -0
  7. package/dist/{src/api → api}/v1/errors.js +1 -0
  8. package/dist/api/v1/errors.js.map +1 -0
  9. package/dist/{src/api → api}/v1/index.js +2 -1
  10. package/dist/api/v1/index.js.map +1 -0
  11. package/dist/{src/events → events}/index.js +2 -21
  12. package/dist/events/index.js.map +1 -0
  13. package/dist/{src/hooks → hooks}/create.js +18 -15
  14. package/dist/hooks/create.js.map +1 -0
  15. package/dist/{src/hooks/enrich.js → hooks/find.js} +29 -52
  16. package/dist/hooks/find.js.map +1 -0
  17. package/dist/{src/hooks → hooks}/index.js +4 -5
  18. package/dist/hooks/index.js.map +1 -0
  19. package/dist/{src/hooks → hooks}/update.js +23 -8
  20. package/dist/hooks/update.js.map +1 -0
  21. package/dist/{src/hooks → hooks}/workaround.js +15 -5
  22. package/dist/hooks/workaround.js.map +1 -0
  23. package/dist/index.js +80 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/{src/models → models}/CustomFieldDefinition.js +17 -22
  26. package/dist/models/CustomFieldDefinition.js.map +1 -0
  27. package/dist/{src/models → models}/CustomFieldValue.js +39 -24
  28. package/dist/models/CustomFieldValue.js.map +1 -0
  29. package/dist/models/index.js +50 -0
  30. package/dist/models/index.js.map +1 -0
  31. package/dist/{src/models → models}/tests/AssociatedTestModel.js +1 -0
  32. package/dist/models/tests/AssociatedTestModel.js.map +1 -0
  33. package/dist/{src/models → models}/tests/TestModel.js +1 -0
  34. package/dist/models/tests/TestModel.js.map +1 -0
  35. package/dist/repository/definition.js +107 -0
  36. package/dist/repository/definition.js.map +1 -0
  37. package/dist/{src/repository → repository}/value.js +36 -27
  38. package/dist/repository/value.js.map +1 -0
  39. package/dist/{src/tests → tests}/api/test-api.js +22 -12
  40. package/dist/tests/api/test-api.js.map +1 -0
  41. package/dist/tests/helpers/index.js +28 -0
  42. package/dist/tests/helpers/index.js.map +1 -0
  43. package/dist/tests/mocks/index.js +60 -0
  44. package/dist/tests/mocks/index.js.map +1 -0
  45. package/dist/{src/tests → tests}/mocks/testModel.js +18 -10
  46. package/dist/tests/mocks/testModel.js.map +1 -0
  47. package/dist/tsconfig.tsbuildinfo +1 -0
  48. package/dist/{src/types → types}/definition/index.js +1 -0
  49. package/dist/types/definition/index.js.map +1 -0
  50. package/dist/{src/types → types}/index.js +1 -0
  51. package/dist/types/index.js.map +1 -0
  52. package/dist/{src/types → types}/value/index.js +1 -0
  53. package/dist/types/value/index.js.map +1 -0
  54. package/dist/{src/utils → utils}/db/index.js +1 -8
  55. package/dist/utils/db/index.js.map +1 -0
  56. package/dist/{src/utils → utils}/logger/index.js +2 -2
  57. package/dist/utils/logger/index.js.map +1 -0
  58. package/dist/{src/utils → utils}/validations/custom-fields.js +1 -0
  59. package/dist/utils/validations/custom-fields.js.map +1 -0
  60. package/dist/utils/validations/custom.js +58 -0
  61. package/dist/utils/validations/custom.js.map +1 -0
  62. package/dist/{src/utils → utils}/validations/index.js +1 -0
  63. package/dist/utils/validations/index.js.map +1 -0
  64. package/dist/utils/validations/type.js +32 -0
  65. package/dist/utils/validations/type.js.map +1 -0
  66. package/package.json +5 -12
  67. package/src/api/v1/definition/index.ts +13 -20
  68. package/src/api/v1/definition/validations.ts +27 -13
  69. package/src/api/v1/index.ts +1 -1
  70. package/src/events/index.ts +1 -23
  71. package/src/hooks/create.ts +6 -12
  72. package/src/hooks/find.ts +82 -23
  73. package/src/hooks/index.ts +2 -4
  74. package/src/hooks/update.ts +11 -5
  75. package/src/hooks/workaround.ts +2 -2
  76. package/src/index.ts +17 -60
  77. package/src/models/CustomFieldDefinition.ts +15 -23
  78. package/src/models/CustomFieldValue.ts +10 -10
  79. package/src/models/index.ts +17 -79
  80. package/src/models/tests/AssociatedTestModel.ts +1 -0
  81. package/src/models/tests/TestModel.ts +1 -0
  82. package/src/repository/definition.ts +41 -27
  83. package/src/repository/value.ts +11 -12
  84. package/src/tests/mocks/events.mock.ts +1 -1
  85. package/src/tests/mocks/{definition.mock.ts → index.ts} +6 -5
  86. package/src/tests/mocks/testModel.ts +7 -12
  87. package/src/types/definition/index.ts +1 -0
  88. package/src/types/index.ts +6 -4
  89. package/src/types/value/index.ts +2 -1
  90. package/src/utils/db/index.ts +0 -7
  91. package/src/utils/logger/index.ts +1 -3
  92. package/src/utils/validations/custom.ts +45 -28
  93. package/src/utils/validations/type.ts +6 -23
  94. package/tsconfig.json +26 -9
  95. package/dist/jest.config.d.ts +0 -12
  96. package/dist/src/api/index.d.ts +0 -2
  97. package/dist/src/api/v1/definition/index.d.ts +0 -2
  98. package/dist/src/api/v1/definition/validations.d.ts +0 -2
  99. package/dist/src/api/v1/definition/validations.js +0 -36
  100. package/dist/src/api/v1/errors.d.ts +0 -2
  101. package/dist/src/api/v1/index.d.ts +0 -2
  102. package/dist/src/errors/index.d.ts +0 -16
  103. package/dist/src/errors/index.js +0 -45
  104. package/dist/src/events/index.d.ts +0 -4
  105. package/dist/src/hooks/create.d.ts +0 -9
  106. package/dist/src/hooks/enrich.d.ts +0 -5
  107. package/dist/src/hooks/find.d.ts +0 -1
  108. package/dist/src/hooks/find.js +0 -29
  109. package/dist/src/hooks/index.d.ts +0 -6
  110. package/dist/src/hooks/update.d.ts +0 -9
  111. package/dist/src/hooks/workaround.d.ts +0 -10
  112. package/dist/src/index.d.ts +0 -11
  113. package/dist/src/index.js +0 -105
  114. package/dist/src/models/CustomFieldDefinition.d.ts +0 -23
  115. package/dist/src/models/CustomFieldValue.d.ts +0 -15
  116. package/dist/src/models/index.d.ts +0 -8
  117. package/dist/src/models/index.js +0 -87
  118. package/dist/src/models/tests/AssociatedTestModel.d.ts +0 -12
  119. package/dist/src/models/tests/TestModel.d.ts +0 -11
  120. package/dist/src/repository/definition.d.ts +0 -17
  121. package/dist/src/repository/definition.js +0 -80
  122. package/dist/src/repository/value.d.ts +0 -24
  123. package/dist/src/tests/api/test-api.d.ts +0 -2
  124. package/dist/src/tests/helpers/database-config.d.ts +0 -15
  125. package/dist/src/tests/helpers/database-config.js +0 -16
  126. package/dist/src/tests/helpers/index.d.ts +0 -2
  127. package/dist/src/tests/helpers/index.js +0 -18
  128. package/dist/src/tests/mocks/definition.mock.d.ts +0 -37
  129. package/dist/src/tests/mocks/definition.mock.js +0 -64
  130. package/dist/src/tests/mocks/events.mock.d.ts +0 -3
  131. package/dist/src/tests/mocks/events.mock.js +0 -19
  132. package/dist/src/tests/mocks/testModel.d.ts +0 -12
  133. package/dist/src/types/definition/index.d.ts +0 -23
  134. package/dist/src/types/index.d.ts +0 -13
  135. package/dist/src/types/value/index.d.ts +0 -15
  136. package/dist/src/utils/constants/index.d.ts +0 -1
  137. package/dist/src/utils/constants/index.js +0 -5
  138. package/dist/src/utils/db/index.d.ts +0 -4
  139. package/dist/src/utils/logger/index.d.ts +0 -2
  140. package/dist/src/utils/validations/custom-fields.d.ts +0 -2
  141. package/dist/src/utils/validations/custom.d.ts +0 -15
  142. package/dist/src/utils/validations/custom.js +0 -42
  143. package/dist/src/utils/validations/index.d.ts +0 -2
  144. package/dist/src/utils/validations/type.d.ts +0 -18
  145. package/dist/src/utils/validations/type.js +0 -50
  146. package/dist/src/utils/validations/validators.d.ts +0 -12
  147. package/dist/src/utils/validations/validators.js +0 -33
  148. package/src/errors/index.ts +0 -42
  149. package/src/hooks/enrich.ts +0 -125
  150. package/src/tests/helpers/database-config.ts +0 -14
  151. package/src/utils/constants/index.ts +0 -2
  152. package/src/utils/validations/validators.ts +0 -34
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
- /* eslint-disable indent */
3
2
  import {
4
3
  Table,
5
4
  Column,
@@ -14,18 +13,16 @@ import {
14
13
  BeforeUpdate,
15
14
  BeforeBulkCreate,
16
15
  BeforeBulkUpdate,
17
- Scopes,
18
16
  } from 'sequelize-typescript';
19
17
  import { sendDimEvent } from '../events';
20
18
  import { CustomFieldDefinition } from '.';
21
19
  import validateValue from '../utils/validations';
22
20
  import * as CustomFieldDefinitionRepo from '../repository/definition';
23
21
  import logger from '../utils/logger';
24
- import { InvalidValueError } from '../errors';
25
22
 
26
23
  @Table({
27
24
  timestamps: true,
28
- })
25
+ })
29
26
  class CustomFieldValue extends Model {
30
27
  @PrimaryKey
31
28
  @Column({
@@ -44,7 +41,7 @@ class CustomFieldValue extends Model {
44
41
 
45
42
  @Column({
46
43
  type: DataType.JSONB,
47
- allowNull: true,
44
+ allowNull: false,
48
45
  })
49
46
  value!: any;
50
47
 
@@ -63,7 +60,8 @@ class CustomFieldValue extends Model {
63
60
  @BeforeBulkCreate
64
61
  @BeforeBulkUpdate
65
62
  static async validateValues(instances: CustomFieldValue[]): Promise<void> {
66
- const ids = instances.map((instance) => instance.customFieldDefinitionId);
63
+ logger.info('CustomFieldValue BeforeBulkCreate/BeforeBulkUpdate', { instances });
64
+ const ids = instances.map(instance => instance.customFieldDefinitionId);
67
65
  const uniqueIds = [...new Set(ids)];
68
66
  const definitions = await CustomFieldDefinitionRepo.findByIds(
69
67
  uniqueIds,
@@ -79,10 +77,10 @@ class CustomFieldValue extends Model {
79
77
  validation,
80
78
  fieldType,
81
79
  } = definitions
82
- .find((definition) => definition.id === instance.customFieldDefinitionId);
80
+ .find(definition => definition.id === instance.customFieldDefinitionId);
83
81
  const isValid = validateValue(instance.value, fieldType, validation);
84
82
  if (!isValid) {
85
- throw new InvalidValueError(instance.value, fieldType);
83
+ throw new Error('Invalid value');
86
84
  }
87
85
  });
88
86
  }
@@ -91,18 +89,19 @@ class CustomFieldValue extends Model {
91
89
  @BeforeCreate
92
90
  @BeforeUpsert
93
91
  static async validateValue(instance: CustomFieldValue): Promise<void> {
92
+ logger.info('CustomFieldValue BeforeCreate/BeforeUpdate', { instance });
94
93
  const { customFieldDefinitionId } = instance;
95
- // eslint-disable-next-line max-len
96
94
  const cfd = await CustomFieldDefinitionRepo.findById(customFieldDefinitionId, { withDisabled: true });
97
95
  const { validation, fieldType } = cfd;
98
96
  const isValid = validateValue(instance.value, fieldType, validation);
99
97
  if (!isValid) {
100
- throw new InvalidValueError(instance.value, fieldType);
98
+ throw new Error('Invalid value');
101
99
  }
102
100
  }
103
101
 
104
102
  @AfterUpsert
105
103
  static afterSaveHandler(instance: CustomFieldValue, options): void {
104
+ logger.info('CustomFieldValue afterSave', { instance });
106
105
  if (options.transaction) {
107
106
  options.transaction.afterCommit(() => sendDimEvent(instance[0]));
108
107
  } else {
@@ -112,3 +111,4 @@ class CustomFieldValue extends Model {
112
111
  }
113
112
 
114
113
  export default CustomFieldValue;
114
+
@@ -1,101 +1,39 @@
1
1
  /* eslint-disable no-param-reassign */
2
- import { DataTypes } from 'sequelize';
3
2
  import type { Sequelize } from 'sequelize-typescript';
4
3
  import logger from '../utils/logger';
4
+ // import addPermanentHooks from '../hooks/permanent-hooks';
5
+
5
6
  import CustomFieldDefinition from './CustomFieldDefinition';
6
7
  import CustomFieldValue from './CustomFieldValue';
7
8
  import TestModel from './tests/TestModel';
8
9
  import AssociatedTestModel from './tests/AssociatedTestModel';
9
10
 
10
- const productionModels = [CustomFieldDefinition, CustomFieldValue];
11
- const testModels = [TestModel, AssociatedTestModel];
11
+ // export const CustomFieldDefinition = CustomFieldDefinitionModel;
12
+ // export { default as CustomFieldDefinition } from './custom-field-definition.model';
12
13
 
13
- const SADOT_MIGRATION_PREFIX = 'sadot-migration';
14
- const SCHEMA_VERSION = 1;
15
- const CUSTOM_FIELDS_SCHEMA_VERSION = `${SADOT_MIGRATION_PREFIX}_${SCHEMA_VERSION}`;
14
+ const productionModels = [CustomFieldDefinition, CustomFieldValue];
15
+ const testModels = [...productionModels, TestModel, AssociatedTestModel];
16
16
 
17
- const initTables = async (sequelize: Sequelize, getUser): Promise<void> => {
17
+ const initTables = async (sequelize: Sequelize): Promise<void> => {
18
18
  logger.info('custom-fields: initialize custom-fields tables');
19
19
  // Detect models and import them to the orm
20
20
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
21
21
  if (!sequelize.addModels) {
22
22
  throw new Error('sequelize instance must have addModels function');
23
23
  }
24
- sequelize.addModels(productionModels);
25
-
26
- CustomFieldDefinition.addScope('userScope', () => {
27
- const user = getUser();
28
- if (user?.permissions) {
29
- return {
30
- where: {
31
- entityId: [
32
- ...Object.keys(user.permissions.fleets),
33
- ...Object.keys(user.permissions.businessModels),
34
- ...Object.keys(user.permissions.demandSources),
35
- ],
36
- },
37
- };
38
- }
39
- return {};
40
- });
24
+ sequelize.addModels(process.env.NODE_ENV === 'test' ? testModels : productionModels);
25
+ await sequelize.dropSchema('custom-fields', { logging: false });
26
+ await sequelize.createSchema('custom-fields', { logging: false });
41
27
 
42
28
  logger.info('custom-fields: models added');
29
+ await CustomFieldDefinition.sync({ alter: true });
30
+ await CustomFieldValue.sync({ alter: true });
43
31
 
44
- const SequelizeMeta = sequelize.define(
45
- 'SequelizeMeta',
46
- {
47
- name: {
48
- type: DataTypes.STRING,
49
- allowNull: false,
50
- unique: true,
51
- primaryKey: true,
52
- autoIncrement: false,
53
- },
54
- },
55
- {
56
- tableName: 'SequelizeMeta',
57
- timestamps: false,
58
- schema: 'public',
59
- },
60
- );
61
- const migrations = await SequelizeMeta.findAll({ raw: true });
62
- const currentSadotSchemaVersion = migrations
63
- .reverse().find((m: any) => m.name.includes(SADOT_MIGRATION_PREFIX));
64
-
65
- if (
66
- !currentSadotSchemaVersion
67
- || (currentSadotSchemaVersion as any).name !== CUSTOM_FIELDS_SCHEMA_VERSION
68
- ) {
69
- await CustomFieldDefinition.sync({ alter: true });
70
- await CustomFieldValue.sync({ alter: true });
71
- await SequelizeMeta.create({ name: CUSTOM_FIELDS_SCHEMA_VERSION });
72
- logger.info('custom-fields: models synced');
32
+ if (process.env.NODE_ENV === 'test') {
33
+ await TestModel.sync({ alter: true });
34
+ await AssociatedTestModel.sync({ alter: true });
73
35
  }
36
+ logger.info('custom-fields: models synced');
74
37
  };
75
38
 
76
- const initTestModels = async (sequelize: Sequelize): Promise<void> => {
77
- logger.info('custom-fields: initialize custom-fields test models');
78
- // Detect models and import them to the orm
79
- // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
80
- if (!sequelize.addModels) {
81
- throw new Error('sequelize instance must have addModels function');
82
- }
83
-
84
- sequelize.addModels(testModels);
85
- await sequelize.dropSchema('custom-fields', { logging: false });
86
- await sequelize.createSchema('custom-fields', { logging: false });
87
-
88
- logger.info('custom-fields: test models added');
89
- await TestModel.sync({ alter: true });
90
- await AssociatedTestModel.sync({ alter: true });
91
- logger.info('custom-fields: test models synced');
92
- };
93
-
94
- export {
95
- CustomFieldValue,
96
- CustomFieldDefinition,
97
- TestModel,
98
- AssociatedTestModel,
99
- initTables,
100
- initTestModels,
101
- };
39
+ export { CustomFieldValue, CustomFieldDefinition, TestModel, AssociatedTestModel, initTables };
@@ -55,3 +55,4 @@ class AssociatedTestModel extends Model {
55
55
  }
56
56
 
57
57
  export default AssociatedTestModel;
58
+
@@ -47,3 +47,4 @@ class TestModel extends Model {
47
47
  }
48
48
 
49
49
  export default TestModel;
50
+
@@ -1,21 +1,24 @@
1
1
  import { Op, WhereOptions } from 'sequelize';
2
- import { CustomFieldDefinition } from '../models';
2
+ import { CustomFieldDefinition, CustomFieldValue } from '../models';
3
3
  import type { CreateCustomFieldDefinition, UpdateCustomFieldDefinition } from '../types/definition';
4
4
 
5
5
  export const create = (data: CreateCustomFieldDefinition): Promise<CustomFieldDefinition> =>
6
6
  CustomFieldDefinition.create(data);
7
7
 
8
8
  export const findAll = (
9
- where: any,
9
+ query: any,
10
10
  options: any = { withDisabled: false },
11
11
  ): Promise<CustomFieldDefinition[]> => {
12
- const queryModel = options.withDisabled
13
- ? CustomFieldDefinition.unscoped()
14
- : CustomFieldDefinition;
15
- return queryModel.scope('userScope').findAll({
16
- where,
17
- transaction: options.transaction,
18
- raw: true,
12
+ if (options.withDisabled) {
13
+ return CustomFieldDefinition.unscoped().findAll({
14
+ where: query,
15
+ include: [CustomFieldValue],
16
+ });
17
+ }
18
+
19
+ return CustomFieldDefinition.findAll({
20
+ where: query,
21
+ include: [CustomFieldValue],
19
22
  });
20
23
  };
21
24
 
@@ -30,9 +33,13 @@ export const findById = (
30
33
  ): Promise<CustomFieldDefinition | null> => {
31
34
  const { withDisabled } = options;
32
35
  if (withDisabled) {
33
- return CustomFieldDefinition.unscoped().scope('userScope').findByPk(id);
36
+ return CustomFieldDefinition.unscoped().findByPk(id, {
37
+ include: [CustomFieldValue],
38
+ });
34
39
  }
35
- return CustomFieldDefinition.scope('userScope').findByPk(id);
40
+ return CustomFieldDefinition.findByPk(id, {
41
+ include: [CustomFieldValue],
42
+ });
36
43
  };
37
44
 
38
45
  export const findByEntityId = async (
@@ -43,22 +50,10 @@ export const findByEntityId = async (
43
50
  transaction: options.transaction,
44
51
  });
45
52
 
46
- export const findByEntityIds = async (
47
- modelType: string,
48
- entityIds: string[],
49
- options: any = {},
50
- ): Promise<CustomFieldDefinition[]> => CustomFieldDefinition.findAll({
51
- where: {
52
- modelType,
53
- entityId: entityIds,
54
- },
55
- transaction: options.transaction,
56
- raw: true,
57
- });
58
-
59
53
  export const findByWhere = (where): Promise<CustomFieldDefinition | null> =>
60
- CustomFieldDefinition.scope('userScope').findOne({
54
+ CustomFieldDefinition.findOne({
61
55
  where,
56
+ include: [CustomFieldValue],
62
57
  });
63
58
 
64
59
  export const findDefinitionsByModels = async (
@@ -68,6 +63,7 @@ export const findDefinitionsByModels = async (
68
63
  const query: WhereOptions<CreateCustomFieldDefinition> = { modelType: { [Op.in]: modelTypes } };
69
64
  return CustomFieldDefinition.findAll({
70
65
  where: query,
66
+ include: [CustomFieldValue],
71
67
  transaction: options?.transaction,
72
68
  });
73
69
  };
@@ -76,7 +72,7 @@ export const update = async (
76
72
  id: string,
77
73
  data: UpdateCustomFieldDefinition,
78
74
  ): Promise<CustomFieldDefinition> => {
79
- const updatedDefinition = (await CustomFieldDefinition.scope('userScope').update(data, {
75
+ const updatedDefinition = (await CustomFieldDefinition.update(data, {
80
76
  where: { id },
81
77
  returning: true,
82
78
  individualHooks: true,
@@ -93,6 +89,7 @@ export const disable = (id: string): Promise<any> =>
93
89
  export const destroy = (id: string): Promise<any> =>
94
90
  CustomFieldDefinition.destroy({ where: { id } });
95
91
 
92
+
96
93
  /**
97
94
  * Return the names of the required fields for a given model
98
95
  */
@@ -100,12 +97,29 @@ export const getRequiredFields = async (
100
97
  modelType: string,
101
98
  modelId: string | string[],
102
99
  entityId: string | string[],
100
+ onlyNull = false,
103
101
  ): Promise<string[]> => {
104
102
  const entityIds = Array.isArray(entityId) ? entityId : [entityId];
103
+ const modelIds = Array.isArray(modelId) ? modelId : [modelId];
104
+ // const valueQuery = Object.assign(
105
+ // {
106
+ // modelId: { [Op.in]: modelIds },
107
+ // },
108
+ // onlyNull ? { value: { [Op.eq]: null } } : null,
109
+ // );
110
+ const valueQuery = onlyNull ? {
111
+ modelId: { [Op.in]: modelIds },
112
+ value: { [Op.eq]: null },
113
+ } : {};
105
114
  const requiredFields = await CustomFieldDefinition.findAll({
106
115
  where: { required: true, modelType, entityId: { [Op.in]: entityIds } },
116
+ include: {
117
+ model: CustomFieldValue,
118
+ where: { ...valueQuery },
119
+ required: false,
120
+ },
107
121
  logging: true,
108
122
  });
109
- const requiredFieldsNames = requiredFields.map((definition) => definition.name);
123
+ const requiredFieldsNames = requiredFields.map(definition => definition.name);
110
124
  return [...new Set(requiredFieldsNames)];
111
125
  };
@@ -1,9 +1,10 @@
1
1
  /* eslint-disable max-len */
2
+ import { Op } from 'sequelize';
3
+
2
4
  import { CustomFieldValue, CustomFieldDefinition } from '../models';
3
5
  import * as DefinitionRepo from './definition';
4
6
  import { CreateCustomFieldValue, ValuesToUpdate } from '../types/value';
5
7
  import logger from '../utils/logger';
6
- import { MissingDefinitionError } from '../errors';
7
8
 
8
9
  export const findByModelIdAndDefinition = async (modelId: string, customFieldDefinitionId: string) =>
9
10
  CustomFieldValue.findAll({ where: { modelId, customFieldDefinitionId }, include: [CustomFieldDefinition] });
@@ -34,9 +35,8 @@ export const findValuesByModelIds = async (modelIds: string[], options?): Promis
34
35
  const { transaction } = options;
35
36
  return CustomFieldValue.findAll({
36
37
  where: { modelId: modelIds },
38
+ include: [CustomFieldDefinition],
37
39
  transaction,
38
- raw: true,
39
- nest: true,
40
40
  });
41
41
  };
42
42
 
@@ -48,7 +48,6 @@ export const findValuesByModelIds = async (modelIds: string[], options?): Promis
48
48
  export const updateValues = async (
49
49
  modelType: string,
50
50
  modelId: string,
51
- identifiers: string[],
52
51
  valuesToUpdate: ValuesToUpdate,
53
52
  options: any = {},
54
53
  ): Promise<CustomFieldValue[]> => {
@@ -56,27 +55,27 @@ export const updateValues = async (
56
55
 
57
56
  const names = Object.keys(valuesToUpdate);
58
57
  const fieldDefinitions = await DefinitionRepo.findAll(
59
- { modelType, name: names, entityId: identifiers },
58
+ { modelType, name: { [Op.in]: names } },
60
59
  { withDisabled: true, transaction: options.transaction },
61
60
  ) || [];
62
61
 
63
- const disabledDefinitions = fieldDefinitions.filter((def) => def.disabled);
62
+ const disabledDefinitions = fieldDefinitions.filter(def => def.disabled);
64
63
  if (fieldDefinitions.length !== names.length) {
65
- const missingDefinitions = names.filter((name) => !fieldDefinitions.some((def) => def.name === name));
66
- throw new MissingDefinitionError(missingDefinitions);
64
+ const missingDefinitions = names.filter(name => !fieldDefinitions.some(def => def.name === name));
65
+ throw new Error(`custom-fields: missing definitions for ${missingDefinitions.join(', ')}`);
67
66
  }
68
67
 
69
- const disabledNames = disabledDefinitions?.map((def) => def.name) || [];
70
- const valuesWithDisabledDefinitions = names.filter((name) => disabledNames.includes(name));
68
+ const disabledNames = disabledDefinitions?.map(def => def.name) || [];
69
+ const valuesWithDisabledDefinitions = names.filter(name => disabledNames.includes(name));
71
70
  if (valuesWithDisabledDefinitions?.length > 0) {
72
71
  logger.warn(`custom-fields: trying to update disabled values: ${valuesWithDisabledDefinitions.join(', ')}`);
73
72
  }
74
73
 
75
- const values: CreateCustomFieldValue[] = names.map((name) => ({
74
+ const values: CreateCustomFieldValue[] = names.map(name => ({
76
75
  modelId,
77
76
  value: valuesToUpdate[name],
78
77
  updatedAt: new Date(),
79
- customFieldDefinitionId: fieldDefinitions.find((def) => def.name === name).id,
78
+ customFieldDefinitionId: fieldDefinitions.find(def => def.name === name).id,
80
79
  }));
81
80
 
82
81
  return Promise.all(values.map(async (value) => {
@@ -5,7 +5,7 @@ export const mockEvent = (events: any, eventName, numberOfEvents) => {
5
5
  return [
6
6
  events.sendObject,
7
7
  (): void => {
8
- const matchingEvents = events.sendObject.mock.calls.filter((call) => call[0] === eventName);
8
+ const matchingEvents = events.sendObject.mock.calls.filter(call => call[0] === eventName);
9
9
  expect(matchingEvents.length).toEqual(numberOfEvents);
10
10
  },
11
11
  ];
@@ -30,8 +30,10 @@ export const booleanField = (modelType: string): CreateCustomFieldDefinition =>
30
30
  export const enumField = (modelType: string, options): CreateCustomFieldDefinition => ({
31
31
  name: 'choices',
32
32
  modelType,
33
- fieldType: 'select',
34
- validation: options,
33
+ fieldType: 'enum',
34
+ validation: {
35
+ enum: options,
36
+ },
35
37
  entityId: uuidv4(),
36
38
  entityType: 'fleetId',
37
39
  });
@@ -47,7 +49,7 @@ export const rangeField = (modelType: string): CreateCustomFieldDefinition => ({
47
49
  entityType: 'fleetId',
48
50
  });
49
51
 
50
- // eslint-disable-next-line max-len
52
+
51
53
  export const createDefinition = (defaults: Partial<CustomFieldDefinitionDTO>): CreateCustomFieldDefinition => ({
52
54
  name: defaults?.name || `def_${uuidv4()}`,
53
55
  modelType: defaults?.modelType || 'TestModel',
@@ -59,8 +61,7 @@ export const createDefinition = (defaults: Partial<CustomFieldDefinitionDTO>): C
59
61
  export const createDefinitions = (
60
62
  defaults: Partial<CustomFieldDefinitionDTO>,
61
63
  length = 1,
62
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
63
- ): CreateCustomFieldDefinition[] => (Array(length).fill({}).map((_) => ({
64
+ ): CreateCustomFieldDefinition[] => (Array(length).fill({}).map(_ => ({
64
65
  name: defaults?.name || `def_${uuidv4()}`,
65
66
  modelType: defaults?.modelType || 'TestModel',
66
67
  fieldType: defaults?.fieldType || 'boolean',
@@ -1,5 +1,6 @@
1
1
  import { TestModel, AssociatedTestModel } from '../../models';
2
2
 
3
+
3
4
  export const createTestModel = (payload = {}) => TestModel.create(payload);
4
5
 
5
6
  export const createTestModels = (fleetId, total: number) => {
@@ -10,28 +11,22 @@ export const createTestModels = (fleetId, total: number) => {
10
11
  return Promise.all<TestModel>(models);
11
12
  };
12
13
 
13
- export const upsertTestModel = (payload) => TestModel.upsert(payload);
14
+ export const upsertTestModel = payload => TestModel.upsert(payload);
14
15
 
15
16
  export const destroyTestModels = () => TestModel.destroy({ truncate: true });
16
17
 
17
- export const getTestModel = (
18
- id: string,
19
- options = {},
20
- ): Promise<TestModel> => TestModel.findByPk(id, options);
18
+ export const getTestModel = (id: string): Promise<TestModel> => TestModel.findByPk(id);
21
19
 
22
- export const getSomeTestModels = (
23
- options = { limit: 1 },
24
- ): Promise<TestModel[]> => TestModel.findAll(options);
20
+ export const getSomeTestModels = (limit = 1): Promise<TestModel[]> => TestModel.findAll({ limit });
25
21
 
26
22
  export const updateTestModel = (payload, query) => TestModel.update(payload, query);
27
23
 
28
24
  // Associations
29
25
  export const createTestModelWithAssociation = async () => {
30
26
  const model = await TestModel.create({});
31
- await AssociatedTestModel.create({ testModelId: model.id });
27
+ const associatedTestModel = await AssociatedTestModel.create({ testModelId: model.id });
32
28
  return model;
33
29
  };
34
30
 
35
- export const getTestModelWithAssociation = (limit = 1) => TestModel.findAll({
36
- limit, include: [AssociatedTestModel],
37
- });
31
+ export const getTestModelWithAssociation = (limit = 1) => TestModel.findAll({ limit, include: [AssociatedTestModel] });
32
+
@@ -20,3 +20,4 @@ export type UpdateCustomFieldDefinition = Partial<CreateCustomFieldDefinition>;
20
20
  export type SerializedCustomFields = {
21
21
  [name: string]: CustomFieldDefinitionDTO & { value: any };
22
22
  };
23
+
@@ -1,3 +1,5 @@
1
+ import type { Sequelize as InnerSequelize } from 'sequelize-typescript';
2
+
1
3
  export type ModelFetcher = (name: string) => any;
2
4
 
3
5
  export type ModelOptions = {
@@ -9,7 +11,7 @@ export type ModelOptions = {
9
11
  }
10
12
 
11
13
  export type CustomFieldOptions= {
12
- models: ModelOptions[];
13
- databaseConfig: any;
14
- getUser: () => any;
15
- };
14
+ models: ModelOptions[];
15
+ innerSequelize?: InnerSequelize;
16
+ databaseConfig: any;
17
+ };
@@ -8,7 +8,8 @@ export interface CustomFieldValueDTO {
8
8
  deletedAt?: Date;
9
9
  }
10
10
 
11
- export type ValuesToUpdate = {[name: string]: any };
12
11
  export type CreateCustomFieldValue = Omit<CustomFieldValueDTO, 'id'>;
13
12
  export type UpdateCustomFieldValue = ValuesToUpdate;
14
13
  export type BulkUpdateCustomFieldValue = Partial<CustomFieldValueDTO>[];
14
+
15
+ export type ValuesToUpdate = {[name: string]: any };
@@ -1,5 +1,4 @@
1
1
  import { Sequelize } from 'sequelize-typescript';
2
- import { QueryTypes } from 'sequelize';
3
2
 
4
3
  export default (databaseConfig: any): Sequelize => {
5
4
  const ENV_DEV = 'test';
@@ -13,9 +12,3 @@ export default (databaseConfig: any): Sequelize => {
13
12
  }
14
13
  return sequelize;
15
14
  };
16
-
17
- export const createSequelizeMeta = (sequelize: Sequelize) => sequelize.query(`
18
- CREATE TABLE IF NOT EXISTS "SequelizeMeta" (
19
- name character varying(255) PRIMARY KEY
20
- );
21
- `, { type: QueryTypes.SELECT });
@@ -1,6 +1,4 @@
1
1
  // eslint-disable-next-line @typescript-eslint/no-var-requires
2
2
  const Logger = require('@autofleet/logger');
3
3
 
4
- const logger = Logger();
5
-
6
- export default logger;
4
+ export default Logger();
@@ -1,39 +1,56 @@
1
- /* eslint-disable no-shadow */
2
- import logger from '../logger';
3
- import { CustomFieldDefinitionType } from './type';
4
- import validators from './validators';
1
+ import { CustomFieldDefinitionType } from "../../models/CustomFieldDefinition";
2
+ import logger from "../logger";
5
3
 
6
- export const mustHaveCustomValidation = {
7
- [CustomFieldDefinitionType.SELECT]: true,
4
+ enum CustomValidations {
5
+ ENUM = 'enum',
6
+ RANGE = 'between'
7
+ }
8
+ const mustHaveCustomValidation = {
9
+ [CustomFieldDefinitionType.ENUM]: true,
10
+ };
11
+ type Validator = (value, validation) => boolean;
12
+ /**
13
+ * Validate {@link CustomValidations.ENUM Enum}
14
+ */
15
+ const validateEnum: Validator = (value, enumValues) => (Array.isArray(enumValues)
16
+ && enumValues.length > 0
17
+ && enumValues.includes(value)
18
+ );
19
+ /**
20
+ * Validate {@link CustomValidations.RANGE Range}
21
+ */
22
+ const validateRange: Validator = (value, range) => {
23
+ const [min, max] = range;
24
+ if (min === undefined || max === undefined) {
25
+ return false;
26
+ }
27
+ return value >= range.min && value <= range.max;
28
+ };
29
+ /**
30
+ * Validators for custom fields
31
+ */
32
+ const customValidators: { [key: string]: Validator } = {
33
+ [CustomValidations.ENUM]: validateEnum,
34
+ [CustomValidations.RANGE]: validateRange,
8
35
  };
9
36
 
10
- /**
11
- * Validates the given validations object against the supported field types and their validators.
12
- * @return true if the validation is valid, false otherwise.
13
- */
14
- export const validateValidation = (valueType, validation) => {
15
- if (!validation) {
16
- if (mustHaveCustomValidation[valueType]) {
37
+ const customValidation = (value, valueType, validations) => {
38
+ const validator = customValidators[valueType];
39
+ const validation = validations[valueType];
40
+ if (mustHaveCustomValidation[valueType]) {
41
+ if (!validation) {
17
42
  logger.error(`No custom validation for custom field type ${valueType} found`);
18
- return false;
43
+ return false; // TODO: Return better error message
19
44
  }
45
+ }
46
+ if (!validation) {
20
47
  return true;
21
48
  }
22
- return true;
23
- };
24
-
25
- /**
26
- * Validates the given value against the custom validation rules for the specified field type.
27
- * If no custom validation rules are provided, it falls back to the default validation.
28
- * @returns true if the value is valid according to the validation rules, false otherwise.
29
- */
30
- const customValidation = (value, valueType, validation) => {
31
- const validator = validators?.[valueType];
32
- if (!validation || !validator) {
33
- return validateValidation(valueType, validation);
49
+ if (!validator) {
50
+ logger.error(`No validator for custom field type ${valueType} found`);
51
+ return false;
34
52
  }
35
- // Always allow null values
36
- return value === null || validator(value, validation);
53
+ return validator(value, validation);
37
54
  };
38
55
 
39
56
  export default customValidation;