@autofleet/sadot 0.0.1-beta.9 → 0.1.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 (60) hide show
  1. package/dist/api/v1/definition/index.js +3 -3
  2. package/dist/api/v1/definition/index.js.map +1 -1
  3. package/dist/api/v1/definition/validations.js +5 -7
  4. package/dist/api/v1/definition/validations.js.map +1 -1
  5. package/dist/api/v1/index.js +1 -1
  6. package/dist/errors/index.js +46 -0
  7. package/dist/errors/index.js.map +1 -0
  8. package/dist/hooks/create.js +5 -3
  9. package/dist/hooks/create.js.map +1 -1
  10. package/dist/hooks/enrich.js +110 -0
  11. package/dist/hooks/enrich.js.map +1 -0
  12. package/dist/hooks/find.js +3 -113
  13. package/dist/hooks/find.js.map +1 -1
  14. package/dist/hooks/index.js +2 -1
  15. package/dist/hooks/index.js.map +1 -1
  16. package/dist/hooks/update.js +0 -10
  17. package/dist/hooks/update.js.map +1 -1
  18. package/dist/index.js +39 -16
  19. package/dist/index.js.map +1 -1
  20. package/dist/models/CustomFieldDefinition.js +21 -16
  21. package/dist/models/CustomFieldDefinition.js.map +1 -1
  22. package/dist/models/CustomFieldValue.js +5 -7
  23. package/dist/models/CustomFieldValue.js.map +1 -1
  24. package/dist/models/index.js +18 -5
  25. package/dist/models/index.js.map +1 -1
  26. package/dist/repository/definition.js +6 -10
  27. package/dist/repository/definition.js.map +1 -1
  28. package/dist/repository/value.js +2 -1
  29. package/dist/repository/value.js.map +1 -1
  30. package/dist/tests/mocks/{index.js → definition.mock.js} +3 -5
  31. package/dist/tests/mocks/definition.mock.js.map +1 -0
  32. package/dist/tsconfig.tsbuildinfo +1 -1
  33. package/dist/utils/validations/custom.js +25 -41
  34. package/dist/utils/validations/custom.js.map +1 -1
  35. package/dist/utils/validations/type.js +27 -9
  36. package/dist/utils/validations/type.js.map +1 -1
  37. package/dist/utils/validations/validators.js +34 -0
  38. package/dist/utils/validations/validators.js.map +1 -0
  39. package/package.json +1 -1
  40. package/src/api/v1/definition/index.ts +5 -5
  41. package/src/api/v1/definition/validations.ts +5 -23
  42. package/src/api/v1/index.ts +1 -1
  43. package/src/errors/index.ts +42 -0
  44. package/src/hooks/create.ts +5 -3
  45. package/src/hooks/enrich.ts +102 -0
  46. package/src/hooks/find.ts +1 -102
  47. package/src/hooks/index.ts +2 -1
  48. package/src/hooks/update.ts +0 -15
  49. package/src/index.ts +37 -15
  50. package/src/models/CustomFieldDefinition.ts +23 -16
  51. package/src/models/CustomFieldValue.ts +7 -7
  52. package/src/models/index.ts +21 -7
  53. package/src/repository/definition.ts +6 -10
  54. package/src/repository/value.ts +2 -1
  55. package/src/tests/mocks/{index.ts → definition.mock.ts} +2 -4
  56. package/src/types/index.ts +1 -3
  57. package/src/utils/validations/custom.ts +26 -44
  58. package/src/utils/validations/type.ts +21 -5
  59. package/src/utils/validations/validators.ts +34 -0
  60. package/dist/tests/mocks/index.js.map +0 -1
@@ -10,10 +10,10 @@ export const findAll = (
10
10
  options: any = { withDisabled: false },
11
11
  ): Promise<CustomFieldDefinition[]> => {
12
12
  if (options.withDisabled) {
13
- return CustomFieldDefinition.unscoped().findAll({ where });
13
+ return CustomFieldDefinition.unscoped().scope('userScope').findAll({ where });
14
14
  }
15
15
 
16
- return CustomFieldDefinition.findAll({ where });
16
+ return CustomFieldDefinition.scope('userScope').findAll({ where });
17
17
  };
18
18
 
19
19
  export const findByIds = (
@@ -27,13 +27,9 @@ export const findById = (
27
27
  ): Promise<CustomFieldDefinition | null> => {
28
28
  const { withDisabled } = options;
29
29
  if (withDisabled) {
30
- return CustomFieldDefinition.unscoped().findByPk(id, {
31
- include: [CustomFieldValue],
32
- });
30
+ return CustomFieldDefinition.unscoped().scope('userScope').findByPk(id);
33
31
  }
34
- return CustomFieldDefinition.findByPk(id, {
35
- include: [CustomFieldValue],
36
- });
32
+ return CustomFieldDefinition.scope('userScope').findByPk(id);
37
33
  };
38
34
 
39
35
  export const findByEntityId = async (
@@ -45,7 +41,7 @@ export const findByEntityId = async (
45
41
  });
46
42
 
47
43
  export const findByWhere = (where): Promise<CustomFieldDefinition | null> =>
48
- CustomFieldDefinition.findOne({
44
+ CustomFieldDefinition.scope('userScope').findOne({
49
45
  where,
50
46
  include: [CustomFieldValue],
51
47
  });
@@ -66,7 +62,7 @@ export const update = async (
66
62
  id: string,
67
63
  data: UpdateCustomFieldDefinition,
68
64
  ): Promise<CustomFieldDefinition> => {
69
- const updatedDefinition = (await CustomFieldDefinition.update(data, {
65
+ const updatedDefinition = (await CustomFieldDefinition.scope('userScope').update(data, {
70
66
  where: { id },
71
67
  returning: true,
72
68
  individualHooks: true,
@@ -3,6 +3,7 @@ import { CustomFieldValue, CustomFieldDefinition } from '../models';
3
3
  import * as DefinitionRepo from './definition';
4
4
  import { CreateCustomFieldValue, ValuesToUpdate } from '../types/value';
5
5
  import logger from '../utils/logger';
6
+ import { MissingDefinitionError } from '../errors';
6
7
 
7
8
  export const findByModelIdAndDefinition = async (modelId: string, customFieldDefinitionId: string) =>
8
9
  CustomFieldValue.findAll({ where: { modelId, customFieldDefinitionId }, include: [CustomFieldDefinition] });
@@ -61,7 +62,7 @@ export const updateValues = async (
61
62
  const disabledDefinitions = fieldDefinitions.filter((def) => def.disabled);
62
63
  if (fieldDefinitions.length !== names.length) {
63
64
  const missingDefinitions = names.filter((name) => !fieldDefinitions.some((def) => def.name === name));
64
- throw new Error(`custom-fields: missing definitions for ${missingDefinitions.join(', ')}`);
65
+ throw new MissingDefinitionError(missingDefinitions);
65
66
  }
66
67
 
67
68
  const disabledNames = disabledDefinitions?.map((def) => def.name) || [];
@@ -30,10 +30,8 @@ export const booleanField = (modelType: string): CreateCustomFieldDefinition =>
30
30
  export const enumField = (modelType: string, options): CreateCustomFieldDefinition => ({
31
31
  name: 'choices',
32
32
  modelType,
33
- fieldType: 'enum',
34
- validation: {
35
- enum: options,
36
- },
33
+ fieldType: 'select',
34
+ validation: options,
37
35
  entityId: uuidv4(),
38
36
  entityType: 'fleetId',
39
37
  });
@@ -1,5 +1,3 @@
1
- import type { Sequelize as InnerSequelize } from 'sequelize-typescript';
2
-
3
1
  export type ModelFetcher = (name: string) => any;
4
2
 
5
3
  export type ModelOptions = {
@@ -12,6 +10,6 @@ export type ModelOptions = {
12
10
 
13
11
  export type CustomFieldOptions= {
14
12
  models: ModelOptions[];
15
- innerSequelize?: InnerSequelize;
16
13
  databaseConfig: any;
14
+ getUser: () => any;
17
15
  };
@@ -1,57 +1,39 @@
1
1
  /* eslint-disable no-shadow */
2
- import { CustomFieldDefinitionType } from '../../models/CustomFieldDefinition';
3
2
  import logger from '../logger';
3
+ import { CustomFieldDefinitionType } from './type';
4
+ import validators from './validators';
4
5
 
5
- enum CustomValidations {
6
- ENUM = 'enum',
7
- RANGE = 'between'
8
- }
9
- const mustHaveCustomValidation = {
10
- [CustomFieldDefinitionType.ENUM]: true,
11
- };
12
- type Validator = (value, validation) => boolean;
13
- /**
14
- * Validate {@link CustomValidations.ENUM Enum}
15
- */
16
- const validateEnum: Validator = (value, enumValues) => (Array.isArray(enumValues)
17
- && enumValues.length > 0
18
- && enumValues.includes(value)
19
- );
20
- /**
21
- * Validate {@link CustomValidations.RANGE Range}
22
- */
23
- const validateRange: Validator = (value, range) => {
24
- const [min, max] = range;
25
- if (min === undefined || max === undefined) {
26
- return false;
27
- }
28
- return value >= range.min && value <= range.max;
29
- };
30
- /**
31
- * Validators for custom fields
32
- */
33
- const customValidators: { [key: string]: Validator } = {
34
- [CustomValidations.ENUM]: validateEnum,
35
- [CustomValidations.RANGE]: validateRange,
6
+ export const mustHaveCustomValidation = {
7
+ [CustomFieldDefinitionType.SELECT]: true,
36
8
  };
37
9
 
38
- const customValidation = (value, valueType, validations) => {
39
- const validator = customValidators[valueType];
40
- const validation = validations[valueType];
41
- if (mustHaveCustomValidation[valueType]) {
42
- if (!validation) {
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]) {
43
17
  logger.error(`No custom validation for custom field type ${valueType} found`);
44
- return false; // TODO: Return better error message
18
+ return false;
45
19
  }
46
- }
47
- if (!validation) {
48
20
  return true;
49
21
  }
50
- if (!validator) {
51
- logger.error(`No validator for custom field type ${valueType} found`);
52
- return false;
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);
53
34
  }
54
- return validator(value, validation);
35
+ // Always allow null values
36
+ return value === null || validator(value, validation);
55
37
  };
56
38
 
57
39
  export default customValidation;
@@ -1,11 +1,27 @@
1
1
  import Joi from '@hapi/joi';
2
- import { CustomFieldDefinitionType } from '../../models/CustomFieldDefinition';
3
-
2
+ /**
3
+ * Supported custom field types
4
+ */
5
+ // eslint-disable-next-line no-shadow
6
+ export enum CustomFieldDefinitionType {
7
+ NUMBER = 'number',
8
+ BOOLEAN = 'boolean',
9
+ DATE = 'date',
10
+ DATETIME = 'datetime',
11
+ TEXT = 'text',
12
+ IMAGE = 'image',
13
+ SELECT = 'select',
14
+ }
4
15
  /**
5
16
  * Validate that the given value is really of type "valueType"
6
17
  * TODO: verify that required field not set to null
7
18
  */
8
- const validateValueType = (value, valueType: CustomFieldDefinitionType) => {
19
+ const validateValueType = (value: unknown, valueType: CustomFieldDefinitionType): boolean => {
20
+ if (value === null) {
21
+ // Null is always allowed
22
+ return true;
23
+ }
24
+
9
25
  switch (valueType) {
10
26
  case CustomFieldDefinitionType.TEXT:
11
27
  return typeof value === 'string';
@@ -16,8 +32,8 @@ const validateValueType = (value, valueType: CustomFieldDefinitionType) => {
16
32
  case CustomFieldDefinitionType.DATE:
17
33
  case CustomFieldDefinitionType.DATETIME:
18
34
  return !Joi.date().validate(value).error;
19
- case CustomFieldDefinitionType.ENUM:
20
- return true;
35
+ case CustomFieldDefinitionType.SELECT:
36
+ return true; // custom validation
21
37
  case CustomFieldDefinitionType.IMAGE:
22
38
  return !Joi.string().uri().validate(value).error;
23
39
  default:
@@ -0,0 +1,34 @@
1
+ // eslint-disable-next-line no-shadow
2
+ export enum CustomValidations {
3
+ SELECT = 'select',
4
+ RANGE = 'between'
5
+ }
6
+
7
+ type Validator = (value, validation) => boolean;
8
+ /**
9
+ * Validate {@link CustomValidations.ENUM Enum}
10
+ */
11
+ const validateEnum: Validator = (value, enumValues) => (Array.isArray(enumValues)
12
+ && enumValues.length > 0
13
+ && enumValues.includes(value)
14
+ );
15
+ /**
16
+ * Validate {@link CustomValidations.RANGE Range}
17
+ */
18
+ const validateRange: Validator = (value, range) => {
19
+ const [min, max] = range;
20
+ if (min === undefined || max === undefined) {
21
+ return false;
22
+ }
23
+ return value >= range.min && value <= range.max;
24
+ };
25
+
26
+ /**
27
+ * Validators for custom fields
28
+ */
29
+ const validators: { [key: string]: Validator } = {
30
+ [CustomValidations.SELECT]: validateEnum,
31
+ [CustomValidations.RANGE]: validateRange,
32
+ };
33
+
34
+ export default validators;
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tests/mocks/index.ts"],"names":[],"mappings":"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"}