@autofleet/sadot 0.12.0 → 0.13.0-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 (124) hide show
  1. package/package.json +3 -1
  2. package/src/api/v1/index.ts +2 -0
  3. package/src/api/v1/validator/index.ts +127 -0
  4. package/src/api/v1/validator/validations.ts +39 -0
  5. package/src/events/index.ts +1 -1
  6. package/src/hooks/hooks.ts +304 -0
  7. package/src/hooks/index.ts +10 -5
  8. package/src/index.ts +6 -0
  9. package/src/models/CustomValidator.ts +76 -0
  10. package/src/models/index.ts +7 -2
  11. package/src/repository/validator.ts +91 -0
  12. package/src/tests/helpers/commonHooks.ts +9 -2
  13. package/src/tests/helpers/index.ts +7 -2
  14. package/src/types/index.ts +1 -0
  15. package/src/utils/validations/schema/README.md +93 -0
  16. package/src/utils/validations/schema/validator-schema.ts +103 -0
  17. package/dist/api/index.d.ts +0 -3
  18. package/dist/api/index.js +0 -12
  19. package/dist/api/v1/definition/index.d.ts +0 -3
  20. package/dist/api/v1/definition/index.js +0 -116
  21. package/dist/api/v1/definition/validations.d.ts +0 -2
  22. package/dist/api/v1/definition/validations.js +0 -77
  23. package/dist/api/v1/errors.d.ts +0 -4
  24. package/dist/api/v1/errors.js +0 -12
  25. package/dist/api/v1/index.d.ts +0 -3
  26. package/dist/api/v1/index.js +0 -11
  27. package/dist/errors/index.d.ts +0 -24
  28. package/dist/errors/index.js +0 -66
  29. package/dist/events/index.d.ts +0 -4
  30. package/dist/events/index.js +0 -50
  31. package/dist/hooks/create.d.ts +0 -10
  32. package/dist/hooks/create.js +0 -95
  33. package/dist/hooks/enrich.d.ts +0 -30
  34. package/dist/hooks/enrich.js +0 -159
  35. package/dist/hooks/find.d.ts +0 -1
  36. package/dist/hooks/find.js +0 -29
  37. package/dist/hooks/index.d.ts +0 -6
  38. package/dist/hooks/index.js +0 -18
  39. package/dist/hooks/update.d.ts +0 -10
  40. package/dist/hooks/update.js +0 -49
  41. package/dist/hooks/utils/updateInstanceValues.d.ts +0 -15
  42. package/dist/hooks/utils/updateInstanceValues.js +0 -50
  43. package/dist/hooks/workaround.d.ts +0 -10
  44. package/dist/hooks/workaround.js +0 -37
  45. package/dist/index.d.ts +0 -13
  46. package/dist/index.js +0 -67
  47. package/dist/models/CustomFieldDefinition.d.ts +0 -25
  48. package/dist/models/CustomFieldDefinition.js +0 -192
  49. package/dist/models/CustomFieldEntries.d.ts +0 -15
  50. package/dist/models/CustomFieldEntries.js +0 -123
  51. package/dist/models/CustomFieldValue.d.ts +0 -16
  52. package/dist/models/CustomFieldValue.js +0 -151
  53. package/dist/models/index.d.ts +0 -17
  54. package/dist/models/index.js +0 -113
  55. package/dist/models/tests/AssociatedTestModel.d.ts +0 -12
  56. package/dist/models/tests/AssociatedTestModel.js +0 -71
  57. package/dist/models/tests/TestModel.d.ts +0 -12
  58. package/dist/models/tests/TestModel.js +0 -69
  59. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.d.ts +0 -10
  60. package/dist/models/tests/contextAwareModels/ContextAwareTestModel.js +0 -53
  61. package/dist/models/tests/contextAwareModels/ContextTestModel.d.ts +0 -13
  62. package/dist/models/tests/contextAwareModels/ContextTestModel.js +0 -47
  63. package/dist/repository/definition.d.ts +0 -36
  64. package/dist/repository/definition.js +0 -121
  65. package/dist/repository/entries.d.ts +0 -13
  66. package/dist/repository/entries.js +0 -92
  67. package/dist/repository/utils/formatValues.d.ts +0 -3
  68. package/dist/repository/utils/formatValues.js +0 -16
  69. package/dist/repository/value.d.ts +0 -28
  70. package/dist/repository/value.js +0 -124
  71. package/dist/scopes/filter.d.ts +0 -30
  72. package/dist/scopes/filter.js +0 -75
  73. package/dist/scopes/helpers/filter.helpers.d.ts +0 -42
  74. package/dist/scopes/helpers/filter.helpers.js +0 -204
  75. package/dist/scopes/index.d.ts +0 -2
  76. package/dist/scopes/index.js +0 -6
  77. package/dist/tests/api/test-api.d.ts +0 -2
  78. package/dist/tests/api/test-api.js +0 -38
  79. package/dist/tests/functional/searching/index.d.ts +0 -8
  80. package/dist/tests/functional/searching/index.js +0 -44
  81. package/dist/tests/helpers/commonHooks.d.ts +0 -5
  82. package/dist/tests/helpers/commonHooks.js +0 -55
  83. package/dist/tests/helpers/database-config.d.ts +0 -16
  84. package/dist/tests/helpers/database-config.js +0 -17
  85. package/dist/tests/helpers/index.d.ts +0 -7
  86. package/dist/tests/helpers/index.js +0 -29
  87. package/dist/tests/mocks/definition.mock.d.ts +0 -48
  88. package/dist/tests/mocks/definition.mock.js +0 -78
  89. package/dist/tests/mocks/events.mock.d.ts +0 -4
  90. package/dist/tests/mocks/events.mock.js +0 -21
  91. package/dist/tests/mocks/testModel.d.ts +0 -12
  92. package/dist/tests/mocks/testModel.js +0 -35
  93. package/dist/types/definition/index.d.ts +0 -25
  94. package/dist/types/definition/index.js +0 -2
  95. package/dist/types/entries/index.d.ts +0 -25
  96. package/dist/types/entries/index.js +0 -2
  97. package/dist/types/index.d.ts +0 -34
  98. package/dist/types/index.js +0 -2
  99. package/dist/types/value/index.d.ts +0 -15
  100. package/dist/types/value/index.js +0 -2
  101. package/dist/utils/constants/index.d.ts +0 -19
  102. package/dist/utils/constants/index.js +0 -22
  103. package/dist/utils/db/index.d.ts +0 -4
  104. package/dist/utils/db/index.js +0 -24
  105. package/dist/utils/helpers/index.d.ts +0 -26
  106. package/dist/utils/helpers/index.js +0 -40
  107. package/dist/utils/init.d.ts +0 -7
  108. package/dist/utils/init.js +0 -109
  109. package/dist/utils/logger/index.d.ts +0 -3
  110. package/dist/utils/logger/index.js +0 -42
  111. package/dist/utils/scopeAttributes.d.ts +0 -2
  112. package/dist/utils/scopeAttributes.js +0 -11
  113. package/dist/utils/validations/index.d.ts +0 -8
  114. package/dist/utils/validations/index.js +0 -41
  115. package/dist/utils/validations/schema/custom-fields.d.ts +0 -3
  116. package/dist/utils/validations/schema/custom-fields.js +0 -9
  117. package/dist/utils/validations/type.d.ts +0 -15
  118. package/dist/utils/validations/type.js +0 -2
  119. package/dist/utils/validations/validators/index.d.ts +0 -14
  120. package/dist/utils/validations/validators/index.js +0 -40
  121. package/dist/utils/validations/validators/select.validator.d.ts +0 -5
  122. package/dist/utils/validations/validators/select.validator.js +0 -12
  123. package/dist/utils/validations/validators/status.validator.d.ts +0 -12
  124. package/dist/utils/validations/validators/status.validator.js +0 -15
@@ -0,0 +1,91 @@
1
+ import type { Transactionable } from 'sequelize';
2
+ import logger from '../utils/logger';
3
+ import { CustomValidator } from '../models';
4
+
5
+ export interface FindValidatorOptions extends Transactionable {
6
+ withDisabled?: boolean;
7
+ }
8
+
9
+ // Make sure this interface is compatible with the Sequelize model
10
+ export interface ValidatorAttributes {
11
+ entityId: string;
12
+ entityType: string;
13
+ modelType: string;
14
+ schema: Record<string, unknown>;
15
+ disabled?: boolean;
16
+ [key: string]: unknown; // Add index signature for Sequelize compatibility
17
+ }
18
+
19
+ export const create = async (
20
+ validatorAttributes: ValidatorAttributes,
21
+ options: Transactionable = {},
22
+ ): Promise<CustomValidator> => {
23
+ logger.debug('custom-validator - create validator');
24
+
25
+ // Use unknown type to bypass TypeScript errors while maintaining compatibility
26
+ const validator = await CustomValidator.create(validatorAttributes as Record<string, unknown>, options);
27
+
28
+ return validator;
29
+ };
30
+
31
+ export const findAll = async (
32
+ where = {},
33
+ options: FindValidatorOptions = { withDisabled: false },
34
+ ): Promise<CustomValidator[]> => {
35
+ logger.debug('custom-validator - find all validators');
36
+
37
+ const { transaction, withDisabled } = options;
38
+
39
+ const fullWhere = withDisabled
40
+ ? where
41
+ : { ...where, disabled: false };
42
+
43
+ const validators = await CustomValidator.findAll({
44
+ where: fullWhere,
45
+ transaction,
46
+ });
47
+
48
+ return validators;
49
+ };
50
+
51
+ export const findAllByModelType = async (
52
+ modelType: string,
53
+ entityId: string,
54
+ options: FindValidatorOptions = { withDisabled: false },
55
+ ): Promise<CustomValidator[]> => {
56
+ logger.debug('custom-validator - find all validators by model type');
57
+
58
+ return findAll(
59
+ {
60
+ modelType,
61
+ entityId,
62
+ },
63
+ options,
64
+ );
65
+ };
66
+
67
+ export const update = async (
68
+ id: string,
69
+ updates: Partial<ValidatorAttributes>,
70
+ options?: Transactionable,
71
+ ): Promise<[number, CustomValidator[]]> => {
72
+ logger.debug('custom-validator - update validator');
73
+
74
+ return CustomValidator.update(
75
+ updates,
76
+ {
77
+ where: { id },
78
+ returning: true,
79
+ ...options,
80
+ },
81
+ );
82
+ };
83
+
84
+ export const disable = async (
85
+ id: string,
86
+ options?: Transactionable,
87
+ ): Promise<[number, CustomValidator[]]> => {
88
+ logger.debug('custom-validator - disable validator');
89
+
90
+ return update(id, { disabled: true }, options);
91
+ };
@@ -9,7 +9,10 @@ import type { Models } from '../../types';
9
9
  export function commonTestHooks(
10
10
  app: Application | null = null,
11
11
  models: Models[] = [{ name: 'TestModel', scopeAttributes: ['fleetId'] }],
12
- options: { useCustomFieldsEntries: boolean } = { useCustomFieldsEntries: false },
12
+ options: { useCustomFieldsEntries: boolean, useValidators?: boolean } = {
13
+ useCustomFieldsEntries: false,
14
+ useValidators: false,
15
+ },
13
16
  ) {
14
17
  let sequelize: Sequelize;
15
18
 
@@ -22,12 +25,16 @@ export function commonTestHooks(
22
25
  getUser: () => undefined,
23
26
  sequelize,
24
27
  useCustomFieldsEntries: options.useCustomFieldsEntries,
28
+ useValidators: options.useValidators,
25
29
  });
26
30
  });
27
31
 
28
32
  afterEach(async () => {
29
33
  jest.clearAllMocks();
30
- await cleanup({ useCustomFieldsEntries: options.useCustomFieldsEntries });
34
+ await cleanup({
35
+ useCustomFieldsEntries: options.useCustomFieldsEntries,
36
+ useValidators: options.useValidators,
37
+ });
31
38
  });
32
39
 
33
40
  afterAll(async () => {
@@ -1,11 +1,11 @@
1
1
  import { generateFilterReplacements } from '@autofleet/sheilta';
2
2
  import {
3
- ContextAwareTestModel, ContextTestModel, CustomFieldDefinition, CustomFieldEntries, TestModel,
3
+ ContextAwareTestModel, ContextTestModel, CustomFieldDefinition, CustomFieldEntries, CustomValidator, TestModel,
4
4
  } from '../../models';
5
5
  import type { CustomFieldOptions } from '../../types';
6
6
 
7
7
  // eslint-disable-next-line import/prefer-default-export
8
- export const cleanup = async (options?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>): Promise<void> => {
8
+ export const cleanup = async (options?: Pick<CustomFieldOptions, 'useCustomFieldsEntries' | 'useValidators'>): Promise<void> => {
9
9
  if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') {
10
10
  await CustomFieldDefinition.unscoped().destroy({ where: {} });
11
11
  await TestModel.destroy({ where: {} });
@@ -15,6 +15,11 @@ export const cleanup = async (options?: Pick<CustomFieldOptions, 'useCustomField
15
15
  if (options?.useCustomFieldsEntries) {
16
16
  await CustomFieldEntries.unscoped().destroy({ where: {} });
17
17
  }
18
+
19
+ // Clean up validators if they were used
20
+ if (options?.useValidators) {
21
+ await CustomValidator.unscoped().destroy({ where: {} });
22
+ }
18
23
  }
19
24
  };
20
25
 
@@ -35,4 +35,5 @@ export type CustomFieldOptions = {
35
35
  getUser: typeof GetUserType;
36
36
  sequelize?: Sequelize;
37
37
  useCustomFieldsEntries?: boolean;
38
+ useValidators?: boolean;
38
39
  };
@@ -0,0 +1,93 @@
1
+ # Schema Validation
2
+
3
+ This directory contains schema validation utilities for the Sadot library, including:
4
+
5
+ 1. **Custom Fields Schemas** - Schema definitions for custom field validation
6
+ 2. **Validator Schemas** - Meta-validation for custom validator JSON schemas
7
+
8
+ ## Custom Fields Schema
9
+
10
+ `custom-fields.ts` defines JSON Schema validation for custom field definitions, ensuring fields are created with valid configurations.
11
+
12
+ ## Validator Schema Validation
13
+
14
+ `validator-schema.ts` provides meta-validation for custom validator schemas. It ensures that:
15
+
16
+ 1. The validator schema follows the expected structure
17
+ 2. The schema is a valid JSON Schema that can be compiled by AJV
18
+ 3. The validation rules defined in the schema are syntactically correct
19
+
20
+ ### Usage
21
+
22
+ The `validateValidatorSchema` function is used by the custom validator API to validate schemas at creation and update time:
23
+
24
+ ```typescript
25
+ import { validateValidatorSchema } from '../utils/validations/schema/validator-schema';
26
+
27
+ // Validates a schema, throws BadRequest if invalid
28
+ validateValidatorSchema(schema);
29
+ ```
30
+
31
+ ### Schema Structure
32
+
33
+ Validator schemas must follow this general structure:
34
+
35
+ ```json
36
+ {
37
+ "type": "object",
38
+ "properties": {
39
+ "before": {
40
+ "type": "object",
41
+ "properties": {
42
+ // Model properties to validate before update
43
+ }
44
+ },
45
+ "after": {
46
+ "type": "object",
47
+ "properties": {
48
+ // Model properties to validate after update/create
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ For create operations, only the `after` section is used. For update operations, both `before` and `after` can be used.
56
+
57
+ ### Conditional Validation
58
+
59
+ The schema can include conditional validation using JSON Schema's `if/then/else` constructs:
60
+
61
+ ```json
62
+ {
63
+ "type": "object",
64
+ "if": {
65
+ "properties": {
66
+ "before": {
67
+ "properties": {
68
+ "status": { "const": "PENDING" }
69
+ }
70
+ }
71
+ }
72
+ },
73
+ "then": {
74
+ "properties": {
75
+ "after": {
76
+ "properties": {
77
+ "status": { "enum": ["APPROVED", "REJECTED"] }
78
+ }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ ```
84
+
85
+ This example validates that if a model's status was "PENDING", it can only be updated to "APPROVED" or "REJECTED".
86
+
87
+ ### Error Handling
88
+
89
+ Schema validation errors are thrown as BadRequest errors with descriptive messages indicating:
90
+
91
+ 1. The specific validation error in the schema
92
+ 2. The path within the schema where the error occurred
93
+ 3. A readable message for API consumers
@@ -0,0 +1,103 @@
1
+ import Ajv from 'ajv';
2
+ import { BadRequest } from '@autofleet/errors';
3
+ import logger from '../../logger';
4
+
5
+ // Instantiate Ajv for meta-validation
6
+ const metaValidator = new Ajv({
7
+ allErrors: true,
8
+ strict: false,
9
+ strictTypes: false,
10
+ });
11
+
12
+ /**
13
+ * Schema for validating JSON Schema objects in custom validators
14
+ * This is a meta-schema to ensure that custom validator schemas are valid Ajv schemas
15
+ */
16
+ const validatorMetaSchema = {
17
+ type: 'object',
18
+ properties: {
19
+ type: { type: 'string', enum: ['object'] },
20
+ properties: {
21
+ type: 'object',
22
+ properties: {
23
+ before: {
24
+ type: 'object',
25
+ properties: {
26
+ type: { type: 'string', enum: ['object'] },
27
+ properties: { type: 'object' },
28
+ },
29
+ },
30
+ after: {
31
+ type: 'object',
32
+ properties: {
33
+ type: { type: 'string', enum: ['object'] },
34
+ properties: { type: 'object' },
35
+ },
36
+ },
37
+ },
38
+ },
39
+ required: {
40
+ type: 'array',
41
+ items: { type: 'string' },
42
+ },
43
+ if: { type: 'object' },
44
+ then: { type: 'object' },
45
+ else: { type: 'object' },
46
+ },
47
+ required: ['type', 'properties'],
48
+ };
49
+
50
+ /**
51
+ * Validates that a given schema is a valid Ajv schema
52
+ * This function is used to validate schemas passed to custom validators
53
+ *
54
+ * @param schema The schema to validate
55
+ * @returns true if valid, throws an error if invalid
56
+ */
57
+ export const validateValidatorSchema = (schema: Record<string, unknown>): boolean => {
58
+ try {
59
+ // First validate the schema structure
60
+ const validateMetaSchema = metaValidator.compile(validatorMetaSchema);
61
+ const isValidStructure = validateMetaSchema(schema);
62
+
63
+ if (!isValidStructure) {
64
+ const errorDetails = validateMetaSchema.errors?.map((err) =>
65
+ `${(err as unknown as { instancePath: string }).instancePath || ''} ${(err as unknown as { message: string }).message || 'Invalid schema structure'}`).join(', ');
66
+
67
+ logger.error('Invalid validator schema structure', {
68
+ errors: validateMetaSchema.errors,
69
+ schema,
70
+ });
71
+
72
+ throw new BadRequest(
73
+ [new Error(`Invalid validator schema structure: ${errorDetails}`)],
74
+ ['Invalid validator schema structure'],
75
+ );
76
+ }
77
+
78
+ // Then try to compile the schema with Ajv to verify it's a valid JSON Schema
79
+ try {
80
+ metaValidator.compile(schema);
81
+ return true;
82
+ } catch (compileError) {
83
+ logger.error('Failed to compile validator schema', { error: compileError, schema });
84
+
85
+ throw new BadRequest(
86
+ [new Error(`Failed to compile validator schema: ${(compileError as Error).message}`)],
87
+ ['Invalid validator schema'],
88
+ );
89
+ }
90
+ } catch (error) {
91
+ if (error instanceof BadRequest) {
92
+ throw error;
93
+ }
94
+
95
+ logger.error('Error validating validator schema', { error, schema });
96
+ throw new BadRequest(
97
+ [new Error(`Error validating validator schema: ${(error as Error).message}`)],
98
+ ['Invalid validator schema'],
99
+ );
100
+ }
101
+ };
102
+
103
+ export default validateValidatorSchema;
@@ -1,3 +0,0 @@
1
- /// <reference types="express" />
2
- declare const router: import("express").Router;
3
- export default router;
package/dist/api/index.js DELETED
@@ -1,12 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- // export the api object
7
- const node_common_1 = require("@autofleet/node-common");
8
- const v1_1 = __importDefault(require("./v1"));
9
- const logger_1 = __importDefault(require("../utils/logger"));
10
- const router = (0, node_common_1.Router)({ logger: logger_1.default });
11
- router.use('/v1', v1_1.default);
12
- exports.default = router;
@@ -1,3 +0,0 @@
1
- /// <reference types="express" />
2
- declare const router: import("express").Router;
3
- export default router;
@@ -1,116 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- const errors_1 = require("@autofleet/errors");
30
- const node_common_1 = require("@autofleet/node-common");
31
- const errors_2 = __importDefault(require("../errors"));
32
- const DefinitionRepo = __importStar(require("../../../repository/definition"));
33
- const validations_1 = require("./validations");
34
- const logger_1 = __importDefault(require("../../../utils/logger"));
35
- const router = (0, node_common_1.Router)({ logger: logger_1.default });
36
- const ENTITY = 'CustomFieldDefinition';
37
- const toPascalCase = (str) => str.replace(/(^\w|-\w)/g, (subStr) => subStr.replace(/-/, '').toUpperCase());
38
- /**
39
- * Create
40
- */
41
- router.post('/', async (req, res) => {
42
- const { modelName } = req.params;
43
- const modelType = toPascalCase(modelName);
44
- try {
45
- const validatedPayload = await (0, validations_1.validateCustomFieldDefinitionCreation)(req.body);
46
- const customFieldDefinition = await DefinitionRepo.create({
47
- ...validatedPayload,
48
- modelType,
49
- });
50
- return res.status(201).json(customFieldDefinition);
51
- }
52
- catch (err) {
53
- logger_1.default.error('Failed to create custom field definition', err);
54
- return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in create ${ENTITY} request` });
55
- }
56
- });
57
- /**
58
- * Get by id
59
- */
60
- router.get('/:customFieldDefinitionId', async (req, res) => {
61
- const { customFieldDefinitionId } = req.params;
62
- try {
63
- const customFieldDefinition = await DefinitionRepo.findById(customFieldDefinitionId);
64
- if (!customFieldDefinition) {
65
- throw new errors_1.ResourceNotFoundError();
66
- }
67
- return res.json(customFieldDefinition);
68
- }
69
- catch (err) {
70
- logger_1.default.error('Failed to fetch custom field definition', err);
71
- return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in get ${ENTITY} request` });
72
- }
73
- });
74
- /**
75
- * Get all
76
- */
77
- router.get('/', async (req, res) => {
78
- const { params: { modelName }, query: { entityIds } } = req;
79
- const modelType = toPascalCase(modelName);
80
- try {
81
- const where = {
82
- modelType,
83
- ...(entityIds?.length > 0 && { entityId: entityIds }),
84
- };
85
- const customFieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true });
86
- return res.json(customFieldDefinitions);
87
- }
88
- catch (err) {
89
- logger_1.default.error('Failed to fetch custom field definitions', err);
90
- return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in get all ${ENTITY} request` });
91
- }
92
- });
93
- /**
94
- * Update
95
- */
96
- router.patch('/:customFieldDefinitionId', async (req, res) => {
97
- const { customFieldDefinitionId, modelName } = req.params;
98
- const modelType = toPascalCase(modelName);
99
- try {
100
- const validatedPayload = await (0, validations_1.validateCustomFieldDefinitionUpdate)(req.body);
101
- const customFieldDefinition = await DefinitionRepo.findByWhere({
102
- id: customFieldDefinitionId,
103
- modelType,
104
- });
105
- if (!customFieldDefinition) {
106
- throw new errors_1.ResourceNotFoundError();
107
- }
108
- const updatedCustomFieldDefinition = await DefinitionRepo.update(customFieldDefinitionId, { ...validatedPayload, modelType });
109
- return res.status(200).json(updatedCustomFieldDefinition);
110
- }
111
- catch (err) {
112
- logger_1.default.error('Failed to patch custom field definition', err);
113
- return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in update ${ENTITY} request` });
114
- }
115
- });
116
- exports.default = router;
@@ -1,2 +0,0 @@
1
- export declare const validateCustomFieldDefinitionCreation: (payload: any) => Promise<any>;
2
- export declare const validateCustomFieldDefinitionUpdate: (payload: any) => Promise<any>;
@@ -1,77 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.validateCustomFieldDefinitionUpdate = exports.validateCustomFieldDefinitionCreation = void 0;
7
- /* eslint-disable newline-per-chained-call */
8
- const joi_1 = __importDefault(require("joi"));
9
- const constants_1 = require("../../../utils/constants");
10
- const FileValidationSchema = joi_1.default.object({
11
- name: joi_1.default.string().required(),
12
- type: joi_1.default.string(),
13
- size: joi_1.default.string(),
14
- addedBy: joi_1.default.string().uuid(),
15
- });
16
- const statusValidationObject = joi_1.default.object({
17
- value: joi_1.default.string().required(),
18
- color: joi_1.default.string().required(),
19
- });
20
- /**
21
- * Schema for the validation of custom field definition
22
- * The only custom validation is for
23
- * {@link CustomFieldDefinitionType.SELECT SELECT}
24
- * and
25
- * {@link CustomFieldDefinitionType.STATUS STATUS}
26
- * field types.
27
- * The rest of the field types are validated by Joi
28
- */
29
- const ValidationSchema = joi_1.default.when('fieldType', {
30
- is: constants_1.CustomFieldDefinitionType.SELECT,
31
- then: joi_1.default.array().required().items(joi_1.default.string()).min(1).unique(),
32
- otherwise: joi_1.default.when('fieldType', {
33
- is: constants_1.CustomFieldDefinitionType.STATUS,
34
- then: joi_1.default.array().required().items(statusValidationObject).min(1).unique('value'),
35
- otherwise: joi_1.default.forbidden(),
36
- }),
37
- });
38
- const DefaultValueSchema = joi_1.default.when('fieldType', {
39
- switch: [
40
- { is: constants_1.CustomFieldDefinitionType.BOOLEAN, then: joi_1.default.boolean().allow(null) },
41
- { is: constants_1.CustomFieldDefinitionType.DATE, then: joi_1.default.date().allow(null) },
42
- { is: constants_1.CustomFieldDefinitionType.DATETIME, then: joi_1.default.date().allow(null) },
43
- { is: constants_1.CustomFieldDefinitionType.FILE, then: joi_1.default.array().items(FileValidationSchema).allow(null) },
44
- { is: constants_1.CustomFieldDefinitionType.IMAGE, then: joi_1.default.array().items(joi_1.default.string().uri()).allow(null) },
45
- { is: constants_1.CustomFieldDefinitionType.NUMBER, then: joi_1.default.number().allow(null) },
46
- { is: constants_1.CustomFieldDefinitionType.SELECT, then: joi_1.default.string().allow(null) },
47
- { is: constants_1.CustomFieldDefinitionType.STATUS, then: joi_1.default.string().allow(null) },
48
- { is: constants_1.CustomFieldDefinitionType.TEXT, then: joi_1.default.string().allow(null) },
49
- ],
50
- });
51
- const CustomFieldDefinitionCreationSchema = joi_1.default.object({
52
- name: joi_1.default.string().required(),
53
- displayName: joi_1.default.string().required(),
54
- validation: ValidationSchema,
55
- defaultValue: DefaultValueSchema,
56
- fieldType: joi_1.default.string().valid(...Object.values(constants_1.CustomFieldDefinitionType)).required(),
57
- entityId: joi_1.default.string().guid().required(),
58
- entityType: joi_1.default.string().required(),
59
- description: joi_1.default.string(),
60
- required: joi_1.default.boolean(),
61
- disabled: joi_1.default.boolean(),
62
- blockEditingFromUI: joi_1.default.boolean(),
63
- }).oxor('required', 'blockEditingFromUI', { isPresent: (value) => value === true });
64
- const CustomFieldDefinitionUpdateSchema = joi_1.default.object({
65
- displayName: joi_1.default.string(),
66
- validation: ValidationSchema,
67
- defaultValue: DefaultValueSchema,
68
- fieldType: joi_1.default.string().valid(...Object.values(constants_1.CustomFieldDefinitionType)),
69
- description: joi_1.default.string().allow(null),
70
- required: joi_1.default.boolean(),
71
- disabled: joi_1.default.boolean(),
72
- blockEditingFromUI: joi_1.default.boolean(),
73
- }).oxor('required', 'blockEditingFromUI', { isPresent: (value) => value === true });
74
- const validateCustomFieldDefinitionCreation = (payload) => CustomFieldDefinitionCreationSchema.validateAsync(payload, { abortEarly: false });
75
- exports.validateCustomFieldDefinitionCreation = validateCustomFieldDefinitionCreation;
76
- const validateCustomFieldDefinitionUpdate = (payload) => CustomFieldDefinitionUpdateSchema.validateAsync(payload, { abortEarly: false });
77
- exports.validateCustomFieldDefinitionUpdate = validateCustomFieldDefinitionUpdate;
@@ -1,4 +0,0 @@
1
- import type { Response } from 'express';
2
- import { type LogPayload } from '@autofleet/errors';
3
- declare const _default: (err: any, res: Response, additionalData?: LogPayload) => void;
4
- export default _default;
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const errors_1 = require("@autofleet/errors");
4
- const joi_1 = require("joi");
5
- const sequelize_1 = require("sequelize");
6
- exports.default = (err, res, additionalData = undefined) => {
7
- let error = err;
8
- if ([joi_1.ValidationError, sequelize_1.ValidationError].some((ErrClass) => err instanceof ErrClass)) {
9
- error = new errors_1.BadRequest([err], null);
10
- }
11
- return (0, errors_1.handleError)(error, res, additionalData);
12
- };
@@ -1,3 +0,0 @@
1
- /// <reference types="express" />
2
- declare const router: import("express").Router;
3
- export default router;
@@ -1,11 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const node_common_1 = require("@autofleet/node-common");
7
- const logger_1 = __importDefault(require("../../utils/logger"));
8
- const definition_1 = __importDefault(require("./definition"));
9
- const router = (0, node_common_1.Router)({ logger: logger_1.default });
10
- router.use('/custom-field-definitions/:modelName', definition_1.default);
11
- exports.default = router;
@@ -1,24 +0,0 @@
1
- import { BadRequest } from '@autofleet/errors';
2
- import type { ValidationError } from 'joi';
3
- import type { EntriesValidationError } from '../types/entries';
4
- export declare class MissingRequiredCustomFieldError extends BadRequest {
5
- constructor(missingFields: string[]);
6
- }
7
- export declare class UnsupportedCustomFieldTypeError extends BadRequest {
8
- constructor(fieldType: string);
9
- }
10
- export declare class UnsupportedCustomValidationError extends BadRequest {
11
- constructor(fieldType: string);
12
- }
13
- export declare class InvalidFieldTypeError extends BadRequest {
14
- constructor(fieldType: string);
15
- }
16
- export declare class InvalidValueError extends BadRequest {
17
- constructor(value: any, fieldDefinitionName: string, joiValidationError: ValidationError);
18
- }
19
- export declare class InvalidEntriesError extends BadRequest {
20
- constructor(modelId: string, validationErrors: EntriesValidationError[]);
21
- }
22
- export declare class MissingDefinitionError extends BadRequest {
23
- constructor(fieldNames: string[]);
24
- }