@autofleet/sadot 1.0.0-beta.1 → 1.0.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.
- package/README.md +5 -0
- package/dist/api/index.d.ts +2 -1
- package/dist/api/index.js +3 -2
- package/dist/api/v1/definition/index.d.ts +2 -1
- package/dist/api/v1/definition/index.js +12 -14
- package/dist/api/v1/definition/validations.js +14 -12
- package/dist/api/v1/errors.d.ts +3 -1
- package/dist/api/v1/errors.js +1 -4
- package/dist/api/v1/index.d.ts +2 -1
- package/dist/api/v1/index.js +5 -2
- package/dist/api/v1/validator/index.d.ts +3 -0
- package/dist/api/v1/validator/index.js +143 -0
- package/dist/api/v1/validator/validations.d.ts +6 -0
- package/dist/api/v1/validator/validations.js +40 -0
- package/dist/errors/index.d.ts +9 -1
- package/dist/errors/index.js +25 -4
- package/dist/events/index.d.ts +2 -1
- package/dist/events/index.js +17 -11
- package/dist/hooks/create.d.ts +2 -2
- package/dist/hooks/create.js +40 -19
- package/dist/hooks/enrich.d.ts +20 -2
- package/dist/hooks/enrich.js +88 -16
- package/dist/hooks/hooks.d.ts +17 -0
- package/dist/hooks/hooks.js +379 -0
- package/dist/hooks/index.d.ts +2 -3
- package/dist/hooks/index.js +6 -7
- package/dist/hooks/update.d.ts +2 -2
- package/dist/hooks/update.js +16 -26
- package/dist/hooks/utils/updateInstanceValues.d.ts +15 -0
- package/dist/hooks/utils/updateInstanceValues.js +50 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -6
- package/dist/models/CustomFieldDefinition.d.ts +1 -0
- package/dist/models/CustomFieldDefinition.js +10 -2
- package/dist/models/CustomFieldEntries.d.ts +15 -0
- package/dist/models/CustomFieldEntries.js +123 -0
- package/dist/models/CustomFieldValue.d.ts +3 -2
- package/dist/models/CustomFieldValue.js +22 -14
- package/dist/models/CustomValidator.d.ts +17 -0
- package/dist/models/CustomValidator.js +98 -0
- package/dist/models/index.d.ts +10 -2
- package/dist/models/index.js +60 -22
- package/dist/repository/definition.d.ts +23 -7
- package/dist/repository/definition.js +36 -7
- package/dist/repository/entries.d.ts +13 -0
- package/dist/repository/entries.js +92 -0
- package/dist/repository/utils/formatValues.d.ts +3 -0
- package/dist/repository/utils/formatValues.js +16 -0
- package/dist/repository/validator.d.ts +21 -0
- package/dist/repository/validator.js +62 -0
- package/dist/repository/value.d.ts +1 -1
- package/dist/repository/value.js +7 -32
- package/dist/scopes/filter.d.ts +5 -22
- package/dist/scopes/filter.js +18 -65
- package/dist/scopes/helpers/filter.helpers.d.ts +42 -0
- package/dist/scopes/helpers/filter.helpers.js +204 -0
- package/dist/tests/api/test-api.js +6 -24
- package/dist/tests/helpers/commonHooks.d.ts +6 -0
- package/dist/tests/helpers/commonHooks.js +62 -0
- package/dist/tests/helpers/database-config.js +1 -1
- package/dist/tests/helpers/index.d.ts +6 -1
- package/dist/tests/helpers/index.js +15 -2
- package/dist/tests/mocks/definition.mock.d.ts +5 -2
- package/dist/tests/mocks/definition.mock.js +10 -1
- package/dist/tests/mocks/events.mock.d.ts +1 -0
- package/dist/tests/mocks/events.mock.js +4 -2
- package/dist/types/definition/index.d.ts +1 -0
- package/dist/types/entries/index.d.ts +25 -0
- package/dist/types/entries/index.js +2 -0
- package/dist/types/index.d.ts +19 -3
- package/dist/utils/constants/index.d.ts +1 -1
- package/dist/utils/helpers/index.d.ts +4 -3
- package/dist/utils/helpers/index.js +22 -30
- package/dist/utils/init.d.ts +5 -3
- package/dist/utils/init.js +13 -11
- package/dist/utils/logger/index.d.ts +1 -0
- package/dist/utils/logger/index.js +34 -0
- package/dist/utils/validations/index.d.ts +7 -1
- package/dist/utils/validations/index.js +28 -7
- package/dist/utils/validations/schema/validator-schema.d.ts +9 -0
- package/dist/utils/validations/schema/validator-schema.js +95 -0
- package/dist/utils/validations/type.d.ts +2 -1
- package/dist/utils/validations/validators/index.js +9 -9
- package/dist/utils/validations/validators/select.validator.js +5 -2
- package/dist/utils/validations/validators/status.validator.js +8 -2
- package/package.json +28 -12
- package/src/api/index.ts +3 -2
- package/src/api/v1/definition/index.ts +20 -23
- package/src/api/v1/definition/validations.ts +16 -16
- package/src/api/v1/errors.ts +4 -7
- package/src/api/v1/index.ts +5 -3
- package/src/api/v1/validator/index.ts +141 -0
- package/src/api/v1/validator/validations.ts +39 -0
- package/src/errors/index.ts +31 -3
- package/src/events/index.ts +25 -13
- package/src/hooks/create.ts +50 -28
- package/src/hooks/enrich.ts +137 -28
- package/src/hooks/hooks.ts +467 -0
- package/src/hooks/index.ts +10 -5
- package/src/hooks/update.ts +20 -7
- package/src/hooks/utils/updateInstanceValues.ts +63 -0
- package/src/index.ts +10 -8
- package/src/models/CustomFieldDefinition.ts +9 -2
- package/src/models/CustomFieldEntries.ts +81 -0
- package/src/models/CustomFieldValue.ts +25 -17
- package/src/models/CustomValidator.ts +78 -0
- package/src/models/index.ts +83 -25
- package/src/repository/definition.ts +62 -14
- package/src/repository/entries.ts +88 -0
- package/src/repository/utils/formatValues.ts +14 -0
- package/src/repository/validator.ts +104 -0
- package/src/repository/value.ts +5 -35
- package/src/scopes/filter.ts +33 -106
- package/src/scopes/helpers/filter.helpers.ts +227 -0
- package/src/tests/api/test-api.ts +4 -2
- package/src/tests/helpers/commonHooks.ts +43 -0
- package/src/tests/helpers/database-config.ts +1 -1
- package/src/tests/helpers/index.ts +18 -2
- package/src/tests/mocks/definition.mock.ts +18 -9
- package/src/tests/mocks/events.mock.ts +4 -1
- package/src/types/definition/index.ts +1 -0
- package/src/types/entries/index.ts +27 -0
- package/src/types/index.ts +20 -3
- package/src/utils/helpers/index.ts +28 -35
- package/src/utils/init.ts +17 -12
- package/src/utils/logger/index.ts +9 -0
- package/src/utils/validations/index.ts +30 -6
- package/src/utils/validations/schema/README.md +93 -0
- package/src/utils/validations/schema/validator-schema.ts +106 -0
- package/src/utils/validations/type.ts +2 -1
- package/src/utils/validations/validators/index.ts +9 -9
- package/src/utils/validations/validators/select.validator.ts +3 -2
- package/src/utils/validations/validators/status.validator.ts +6 -2
- package/tsconfig.build.json +7 -0
- package/tsconfig.json +1 -1
package/README.md
ADDED
package/dist/api/index.d.ts
CHANGED
package/dist/api/index.js
CHANGED
|
@@ -4,8 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
// export the api object
|
|
7
|
-
const
|
|
7
|
+
const node_common_1 = require("@autofleet/node-common");
|
|
8
8
|
const v1_1 = __importDefault(require("./v1"));
|
|
9
|
-
const
|
|
9
|
+
const logger_1 = __importDefault(require("../utils/logger"));
|
|
10
|
+
const router = (0, node_common_1.Router)({ logger: logger_1.default });
|
|
10
11
|
router.use('/v1', v1_1.default);
|
|
11
12
|
exports.default = router;
|
|
@@ -27,12 +27,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
const errors_1 = require("@autofleet/errors");
|
|
30
|
-
const
|
|
30
|
+
const node_common_1 = require("@autofleet/node-common");
|
|
31
31
|
const errors_2 = __importDefault(require("../errors"));
|
|
32
32
|
const DefinitionRepo = __importStar(require("../../../repository/definition"));
|
|
33
33
|
const validations_1 = require("./validations");
|
|
34
34
|
const logger_1 = __importDefault(require("../../../utils/logger"));
|
|
35
|
-
const router = (0,
|
|
35
|
+
const router = (0, node_common_1.Router)({ logger: logger_1.default });
|
|
36
36
|
const ENTITY = 'CustomFieldDefinition';
|
|
37
37
|
const toPascalCase = (str) => str.replace(/(^\w|-\w)/g, (subStr) => subStr.replace(/-/, '').toUpperCase());
|
|
38
38
|
/**
|
|
@@ -51,7 +51,7 @@ router.post('/', async (req, res) => {
|
|
|
51
51
|
}
|
|
52
52
|
catch (err) {
|
|
53
53
|
logger_1.default.error('Failed to create custom field definition', err);
|
|
54
|
-
return (0, errors_2.default)(err, res, { message: `Error in create ${ENTITY} request` });
|
|
54
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in create ${ENTITY} request` });
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
/**
|
|
@@ -68,27 +68,26 @@ router.get('/:customFieldDefinitionId', async (req, res) => {
|
|
|
68
68
|
}
|
|
69
69
|
catch (err) {
|
|
70
70
|
logger_1.default.error('Failed to fetch custom field definition', err);
|
|
71
|
-
return (0, errors_2.default)(err, res, { message: `Error in get ${ENTITY} request` });
|
|
71
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in get ${ENTITY} request` });
|
|
72
72
|
}
|
|
73
73
|
});
|
|
74
74
|
/**
|
|
75
75
|
* Get all
|
|
76
76
|
*/
|
|
77
77
|
router.get('/', async (req, res) => {
|
|
78
|
-
const { modelName } = req
|
|
79
|
-
const { entityIds } = req.query;
|
|
78
|
+
const { params: { modelName }, query: { entityIds } } = req;
|
|
80
79
|
const modelType = toPascalCase(modelName);
|
|
81
80
|
try {
|
|
82
|
-
const where = {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
const customFieldDefinitions = await DefinitionRepo.findAll(
|
|
81
|
+
const where = {
|
|
82
|
+
modelType,
|
|
83
|
+
...(entityIds?.length > 0 && { entityId: entityIds }),
|
|
84
|
+
};
|
|
85
|
+
const customFieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: true });
|
|
87
86
|
return res.json(customFieldDefinitions);
|
|
88
87
|
}
|
|
89
88
|
catch (err) {
|
|
90
89
|
logger_1.default.error('Failed to fetch custom field definitions', err);
|
|
91
|
-
return (0, errors_2.default)(err, res, { message: `Error in get all ${ENTITY} request` });
|
|
90
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in get all ${ENTITY} request` });
|
|
92
91
|
}
|
|
93
92
|
});
|
|
94
93
|
/**
|
|
@@ -98,7 +97,6 @@ router.patch('/:customFieldDefinitionId', async (req, res) => {
|
|
|
98
97
|
const { customFieldDefinitionId, modelName } = req.params;
|
|
99
98
|
const modelType = toPascalCase(modelName);
|
|
100
99
|
try {
|
|
101
|
-
// eslint-disable-next-line max-len
|
|
102
100
|
const validatedPayload = await (0, validations_1.validateCustomFieldDefinitionUpdate)(req.body);
|
|
103
101
|
const customFieldDefinition = await DefinitionRepo.findByWhere({
|
|
104
102
|
id: customFieldDefinitionId,
|
|
@@ -112,7 +110,7 @@ router.patch('/:customFieldDefinitionId', async (req, res) => {
|
|
|
112
110
|
}
|
|
113
111
|
catch (err) {
|
|
114
112
|
logger_1.default.error('Failed to patch custom field definition', err);
|
|
115
|
-
return (0, errors_2.default)(err, res, { message: `Error in update ${ENTITY} request` });
|
|
113
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in update ${ENTITY} request` });
|
|
116
114
|
}
|
|
117
115
|
});
|
|
118
116
|
exports.default = router;
|
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.validateCustomFieldDefinitionUpdate = exports.validateCustomFieldDefinitionCreation = void 0;
|
|
7
|
+
/* eslint-disable newline-per-chained-call */
|
|
7
8
|
const joi_1 = __importDefault(require("joi"));
|
|
8
9
|
const constants_1 = require("../../../utils/constants");
|
|
9
10
|
const FileValidationSchema = joi_1.default.object({
|
|
@@ -16,7 +17,6 @@ const statusValidationObject = joi_1.default.object({
|
|
|
16
17
|
value: joi_1.default.string().required(),
|
|
17
18
|
color: joi_1.default.string().required(),
|
|
18
19
|
});
|
|
19
|
-
const statusValidationObjectSchema = joi_1.default.array().items(statusValidationObject).min(1).unique('value');
|
|
20
20
|
/**
|
|
21
21
|
* Schema for the validation of custom field definition
|
|
22
22
|
* The only custom validation is for
|
|
@@ -28,23 +28,23 @@ const statusValidationObjectSchema = joi_1.default.array().items(statusValidatio
|
|
|
28
28
|
*/
|
|
29
29
|
const ValidationSchema = joi_1.default.when('fieldType', {
|
|
30
30
|
is: constants_1.CustomFieldDefinitionType.SELECT,
|
|
31
|
-
then: joi_1.default.array().items(joi_1.default.string()).min(1).unique(),
|
|
32
|
-
otherwise: joi_1.default.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
37
|
});
|
|
38
38
|
const DefaultValueSchema = joi_1.default.when('fieldType', {
|
|
39
39
|
switch: [
|
|
40
40
|
{ is: constants_1.CustomFieldDefinitionType.BOOLEAN, then: joi_1.default.boolean().allow(null) },
|
|
41
41
|
{ is: constants_1.CustomFieldDefinitionType.DATE, then: joi_1.default.date().allow(null) },
|
|
42
42
|
{ is: constants_1.CustomFieldDefinitionType.DATETIME, then: joi_1.default.date().allow(null) },
|
|
43
|
-
{ is: constants_1.CustomFieldDefinitionType.FILE, then: FileValidationSchema },
|
|
44
|
-
{ is: constants_1.CustomFieldDefinitionType.IMAGE, then: joi_1.default.string().uri().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
45
|
{ is: constants_1.CustomFieldDefinitionType.NUMBER, then: joi_1.default.number().allow(null) },
|
|
46
46
|
{ is: constants_1.CustomFieldDefinitionType.SELECT, then: joi_1.default.string().allow(null) },
|
|
47
|
-
{ is: constants_1.CustomFieldDefinitionType.STATUS, then:
|
|
47
|
+
{ is: constants_1.CustomFieldDefinitionType.STATUS, then: joi_1.default.string().allow(null) },
|
|
48
48
|
{ is: constants_1.CustomFieldDefinitionType.TEXT, then: joi_1.default.string().allow(null) },
|
|
49
49
|
],
|
|
50
50
|
});
|
|
@@ -59,7 +59,8 @@ const CustomFieldDefinitionCreationSchema = joi_1.default.object({
|
|
|
59
59
|
description: joi_1.default.string(),
|
|
60
60
|
required: joi_1.default.boolean(),
|
|
61
61
|
disabled: joi_1.default.boolean(),
|
|
62
|
-
|
|
62
|
+
blockEditingFromUI: joi_1.default.boolean(),
|
|
63
|
+
}).oxor('required', 'blockEditingFromUI', { isPresent: (value) => value === true });
|
|
63
64
|
const CustomFieldDefinitionUpdateSchema = joi_1.default.object({
|
|
64
65
|
displayName: joi_1.default.string(),
|
|
65
66
|
validation: ValidationSchema,
|
|
@@ -68,7 +69,8 @@ const CustomFieldDefinitionUpdateSchema = joi_1.default.object({
|
|
|
68
69
|
description: joi_1.default.string().allow(null),
|
|
69
70
|
required: joi_1.default.boolean(),
|
|
70
71
|
disabled: joi_1.default.boolean(),
|
|
71
|
-
|
|
72
|
+
blockEditingFromUI: joi_1.default.boolean(),
|
|
73
|
+
}).oxor('required', 'blockEditingFromUI', { isPresent: (value) => value === true });
|
|
72
74
|
const validateCustomFieldDefinitionCreation = (payload) => CustomFieldDefinitionCreationSchema.validateAsync(payload, { abortEarly: false });
|
|
73
75
|
exports.validateCustomFieldDefinitionCreation = validateCustomFieldDefinitionCreation;
|
|
74
76
|
const validateCustomFieldDefinitionUpdate = (payload) => CustomFieldDefinitionUpdateSchema.validateAsync(payload, { abortEarly: false });
|
package/dist/api/v1/errors.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Response } from 'express';
|
|
2
|
+
import { type LogPayload } from '@autofleet/errors';
|
|
3
|
+
declare const _default: (err: any, res: Response, additionalData?: LogPayload) => void;
|
|
2
4
|
export default _default;
|
package/dist/api/v1/errors.js
CHANGED
|
@@ -5,10 +5,7 @@ const joi_1 = require("joi");
|
|
|
5
5
|
const sequelize_1 = require("sequelize");
|
|
6
6
|
exports.default = (err, res, additionalData = undefined) => {
|
|
7
7
|
let error = err;
|
|
8
|
-
if (err instanceof
|
|
9
|
-
error = new errors_1.BadRequest([err], null);
|
|
10
|
-
}
|
|
11
|
-
if (err instanceof sequelize_1.ValidationError) {
|
|
8
|
+
if ([joi_1.ValidationError, sequelize_1.ValidationError].some((ErrClass) => err instanceof ErrClass)) {
|
|
12
9
|
error = new errors_1.BadRequest([err], null);
|
|
13
10
|
}
|
|
14
11
|
return (0, errors_1.handleError)(error, res, additionalData);
|
package/dist/api/v1/index.d.ts
CHANGED
package/dist/api/v1/index.js
CHANGED
|
@@ -3,8 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const
|
|
6
|
+
const node_common_1 = require("@autofleet/node-common");
|
|
7
|
+
const logger_1 = __importDefault(require("../../utils/logger"));
|
|
7
8
|
const definition_1 = __importDefault(require("./definition"));
|
|
8
|
-
const
|
|
9
|
+
const validator_1 = __importDefault(require("./validator"));
|
|
10
|
+
const router = (0, node_common_1.Router)({ logger: logger_1.default });
|
|
9
11
|
router.use('/custom-field-definitions/:modelName', definition_1.default);
|
|
12
|
+
router.use('/custom-validators/:modelName', validator_1.default);
|
|
10
13
|
exports.default = router;
|
|
@@ -0,0 +1,143 @@
|
|
|
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 http_status_codes_1 = require("http-status-codes");
|
|
32
|
+
const errors_2 = __importDefault(require("../errors"));
|
|
33
|
+
const ValidatorRepo = __importStar(require("../../../repository/validator"));
|
|
34
|
+
const validations_1 = __importDefault(require("./validations"));
|
|
35
|
+
const logger_1 = __importDefault(require("../../../utils/logger"));
|
|
36
|
+
const validator_schema_1 = require("../../../utils/validations/schema/validator-schema");
|
|
37
|
+
const router = (0, node_common_1.Router)({ logger: logger_1.default });
|
|
38
|
+
const ENTITY = 'CustomValidator';
|
|
39
|
+
/**
|
|
40
|
+
* Create
|
|
41
|
+
*/
|
|
42
|
+
router.post('/', async (req, res) => {
|
|
43
|
+
const { modelName } = req.params;
|
|
44
|
+
try {
|
|
45
|
+
// Validate the request body
|
|
46
|
+
const validatedPayload = await validations_1.default.create.validateAsync(req.body);
|
|
47
|
+
// Validate that the schema is a valid AJV schema
|
|
48
|
+
(0, validator_schema_1.validateValidatorSchema)(validatedPayload.schema);
|
|
49
|
+
const validator = await ValidatorRepo.create({
|
|
50
|
+
...validatedPayload,
|
|
51
|
+
modelType: modelName,
|
|
52
|
+
});
|
|
53
|
+
return res.status(http_status_codes_1.StatusCodes.CREATED).json(validator);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in create ${ENTITY} request` });
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* Get all
|
|
61
|
+
*/
|
|
62
|
+
router.get('/', async (req, res) => {
|
|
63
|
+
try {
|
|
64
|
+
const { modelName } = req.params;
|
|
65
|
+
const { entityId, entityType } = req.query;
|
|
66
|
+
const where = {
|
|
67
|
+
modelType: modelName,
|
|
68
|
+
...(entityId && { entityId }),
|
|
69
|
+
...(entityType && { entityType }),
|
|
70
|
+
};
|
|
71
|
+
const validators = await ValidatorRepo.findAll(where);
|
|
72
|
+
return res.status(http_status_codes_1.StatusCodes.OK).json({ validators });
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in get all ${ENTITY} request` });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* Get by id
|
|
80
|
+
*/
|
|
81
|
+
router.get('/:validatorId', async (req, res) => {
|
|
82
|
+
try {
|
|
83
|
+
const { validatorId, modelName } = req.params;
|
|
84
|
+
// Include disabled validators when fetching by ID
|
|
85
|
+
const validators = await ValidatorRepo.findAll({ id: validatorId, modelType: modelName }, { withDisabled: true });
|
|
86
|
+
if (!validators.length) {
|
|
87
|
+
throw new errors_1.ResourceNotFoundError('Validator not found');
|
|
88
|
+
}
|
|
89
|
+
return res.status(http_status_codes_1.StatusCodes.OK).json(validators[0]);
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in get ${ENTITY} request` });
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* Update
|
|
97
|
+
*/
|
|
98
|
+
router.patch('/:validatorId', async (req, res) => {
|
|
99
|
+
try {
|
|
100
|
+
const { validatorId } = req.params;
|
|
101
|
+
// Validate the request body
|
|
102
|
+
const validatedPayload = await validations_1.default.update.validateAsync(req.body);
|
|
103
|
+
// If schema is included in the update, validate that it's a valid AJV schema
|
|
104
|
+
if (validatedPayload.schema) {
|
|
105
|
+
(0, validator_schema_1.validateValidatorSchema)(validatedPayload.schema);
|
|
106
|
+
}
|
|
107
|
+
// First verify the validator exists, including disabled ones
|
|
108
|
+
const existingValidators = await ValidatorRepo.findAll({ id: validatorId }, { withDisabled: true });
|
|
109
|
+
if (!existingValidators.length) {
|
|
110
|
+
throw new errors_1.ResourceNotFoundError('Validator not found');
|
|
111
|
+
}
|
|
112
|
+
const [count, validators] = await ValidatorRepo.update(validatorId, validatedPayload);
|
|
113
|
+
if (!count) {
|
|
114
|
+
throw new errors_1.ResourceNotFoundError('Validator not found');
|
|
115
|
+
}
|
|
116
|
+
return res.status(http_status_codes_1.StatusCodes.OK).json(validators[0]);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in update ${ENTITY} request` });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
/**
|
|
123
|
+
* Delete (disable)
|
|
124
|
+
*/
|
|
125
|
+
router.delete('/:validatorId', async (req, res) => {
|
|
126
|
+
try {
|
|
127
|
+
const { validatorId } = req.params;
|
|
128
|
+
// First verify the validator exists, including disabled ones
|
|
129
|
+
const existingValidators = await ValidatorRepo.findAll({ id: validatorId }, { withDisabled: true });
|
|
130
|
+
if (!existingValidators.length) {
|
|
131
|
+
throw new errors_1.ResourceNotFoundError('Validator not found');
|
|
132
|
+
}
|
|
133
|
+
const [count] = await ValidatorRepo.disable(validatorId);
|
|
134
|
+
if (!count) {
|
|
135
|
+
throw new errors_1.ResourceNotFoundError('Validator failed to be disabled');
|
|
136
|
+
}
|
|
137
|
+
return res.status(http_status_codes_1.StatusCodes.NO_CONTENT).send();
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
return (0, errors_2.default)(err, res, { logger: logger_1.default, message: `Error in delete ${ENTITY} request` });
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
exports.default = router;
|
|
@@ -0,0 +1,40 @@
|
|
|
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 joi_1 = __importDefault(require("joi"));
|
|
7
|
+
// Schema for validating JSON Schema objects
|
|
8
|
+
const jsonSchemaValidation = joi_1.default.object().unknown(true);
|
|
9
|
+
const validationSchemas = {
|
|
10
|
+
create: joi_1.default.object({
|
|
11
|
+
entityId: joi_1.default.string().uuid().required(),
|
|
12
|
+
entityType: joi_1.default.string().required(),
|
|
13
|
+
schema: joi_1.default.object({
|
|
14
|
+
type: joi_1.default.string().valid('object').required(),
|
|
15
|
+
properties: joi_1.default.object({
|
|
16
|
+
before: jsonSchemaValidation,
|
|
17
|
+
after: jsonSchemaValidation,
|
|
18
|
+
}).required(),
|
|
19
|
+
if: joi_1.default.object().optional(),
|
|
20
|
+
then: joi_1.default.object().optional(),
|
|
21
|
+
else: joi_1.default.object().optional(),
|
|
22
|
+
}).required(),
|
|
23
|
+
}),
|
|
24
|
+
update: joi_1.default.object({
|
|
25
|
+
entityId: joi_1.default.string().uuid(),
|
|
26
|
+
entityType: joi_1.default.string(),
|
|
27
|
+
schema: joi_1.default.object({
|
|
28
|
+
type: joi_1.default.string().valid('object'),
|
|
29
|
+
properties: joi_1.default.object({
|
|
30
|
+
before: jsonSchemaValidation,
|
|
31
|
+
after: jsonSchemaValidation,
|
|
32
|
+
}),
|
|
33
|
+
if: joi_1.default.object().optional(),
|
|
34
|
+
then: joi_1.default.object().optional(),
|
|
35
|
+
else: joi_1.default.object().optional(),
|
|
36
|
+
}),
|
|
37
|
+
disabled: joi_1.default.boolean(),
|
|
38
|
+
}).min(1),
|
|
39
|
+
};
|
|
40
|
+
exports.default = validationSchemas;
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { BadRequest } from '@autofleet/errors';
|
|
2
|
+
import type { ValidationError } from 'joi';
|
|
3
|
+
import type { EntriesValidationError } from '../types/entries';
|
|
2
4
|
export declare class MissingRequiredCustomFieldError extends BadRequest {
|
|
3
5
|
constructor(missingFields: string[]);
|
|
4
6
|
}
|
|
@@ -8,8 +10,14 @@ export declare class UnsupportedCustomFieldTypeError extends BadRequest {
|
|
|
8
10
|
export declare class UnsupportedCustomValidationError extends BadRequest {
|
|
9
11
|
constructor(fieldType: string);
|
|
10
12
|
}
|
|
13
|
+
export declare class InvalidFieldTypeError extends BadRequest {
|
|
14
|
+
constructor(fieldType: string);
|
|
15
|
+
}
|
|
11
16
|
export declare class InvalidValueError extends BadRequest {
|
|
12
|
-
constructor(value: any,
|
|
17
|
+
constructor(value: any, fieldDefinitionName: string, joiValidationError: ValidationError);
|
|
18
|
+
}
|
|
19
|
+
export declare class InvalidEntriesError extends BadRequest {
|
|
20
|
+
constructor(modelId: string, validationErrors: EntriesValidationError[]);
|
|
13
21
|
}
|
|
14
22
|
export declare class MissingDefinitionError extends BadRequest {
|
|
15
23
|
constructor(fieldNames: string[]);
|
package/dist/errors/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MissingDefinitionError = exports.InvalidValueError = exports.UnsupportedCustomValidationError = exports.UnsupportedCustomFieldTypeError = exports.MissingRequiredCustomFieldError = void 0;
|
|
3
|
+
exports.MissingDefinitionError = exports.InvalidEntriesError = exports.InvalidValueError = exports.InvalidFieldTypeError = exports.UnsupportedCustomValidationError = exports.UnsupportedCustomFieldTypeError = exports.MissingRequiredCustomFieldError = void 0;
|
|
4
4
|
/* eslint-disable max-classes-per-file */
|
|
5
5
|
const errors_1 = require("@autofleet/errors");
|
|
6
6
|
class MissingRequiredCustomFieldError extends errors_1.BadRequest {
|
|
@@ -27,14 +27,35 @@ class UnsupportedCustomValidationError extends errors_1.BadRequest {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
exports.UnsupportedCustomValidationError = UnsupportedCustomValidationError;
|
|
30
|
+
class InvalidFieldTypeError extends errors_1.BadRequest {
|
|
31
|
+
constructor(fieldType) {
|
|
32
|
+
const err = new Error(`Invalid field type ${fieldType}`);
|
|
33
|
+
super([err], null, null);
|
|
34
|
+
this.message = 'INVALID_FIELD_TYPE';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.InvalidFieldTypeError = InvalidFieldTypeError;
|
|
30
38
|
class InvalidValueError extends errors_1.BadRequest {
|
|
31
|
-
constructor(value,
|
|
32
|
-
const
|
|
39
|
+
constructor(value, fieldDefinitionName, joiValidationError) {
|
|
40
|
+
const formattedErrorMessage = joiValidationError.message
|
|
41
|
+
.replace(/"/g, '')
|
|
42
|
+
.replace('value', `'${fieldDefinitionName}'`);
|
|
43
|
+
const formattedValue = typeof value === 'object' ? JSON.stringify(value) : value;
|
|
44
|
+
const invalidValueMessage = `Invalid Value on field '${fieldDefinitionName}'. ${formattedErrorMessage}. received: '${formattedValue}'`;
|
|
45
|
+
const err = new Error(invalidValueMessage);
|
|
33
46
|
super([err], null, null);
|
|
34
|
-
this.message =
|
|
47
|
+
this.message = invalidValueMessage;
|
|
35
48
|
}
|
|
36
49
|
}
|
|
37
50
|
exports.InvalidValueError = InvalidValueError;
|
|
51
|
+
class InvalidEntriesError extends errors_1.BadRequest {
|
|
52
|
+
constructor(modelId, validationErrors) {
|
|
53
|
+
const errors = validationErrors.map((validationError) => new InvalidValueError(validationError.value, validationError.fieldDefinitionName, validationError.joiValidationError));
|
|
54
|
+
super(errors, null, null);
|
|
55
|
+
this.message = `Invalid entries on ${modelId}\n${validationErrors.map((validationError) => (`${validationError.fieldDefinitionName} - ${validationError.joiValidationError.message}`)).join('\n')}`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.InvalidEntriesError = InvalidEntriesError;
|
|
38
59
|
class MissingDefinitionError extends errors_1.BadRequest {
|
|
39
60
|
constructor(fieldNames) {
|
|
40
61
|
const err = new Error(`Missing custom field definition for field ${fieldNames.join(',')}`);
|
package/dist/events/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Events from '@autofleet/events';
|
|
2
|
+
import type { CustomFieldDefinition, CustomFieldEntries, CustomFieldValue, CustomValidator } from '../models';
|
|
2
3
|
declare const events: Events;
|
|
3
|
-
export declare const sendDimEvent: (instance:
|
|
4
|
+
export declare const sendDimEvent: (instance: CustomFieldDefinition | CustomFieldValue | CustomFieldEntries | CustomValidator) => void;
|
|
4
5
|
export default events;
|
package/dist/events/index.js
CHANGED
|
@@ -5,20 +5,22 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.sendDimEvent = void 0;
|
|
7
7
|
const events_1 = __importDefault(require("@autofleet/events"));
|
|
8
|
+
const zehut_1 = require("@autofleet/zehut");
|
|
8
9
|
const logger_1 = __importDefault(require("../utils/logger"));
|
|
9
|
-
const events = new events_1.default({
|
|
10
|
-
|
|
10
|
+
const events = new events_1.default({
|
|
11
|
+
logger: logger_1.default,
|
|
12
|
+
getUserId: (payload) => payload?.user_id ?? (0, zehut_1.getUser)()?.id ?? null,
|
|
13
|
+
});
|
|
14
|
+
const KEYS_TO_CONVERT = ['value', 'defaultValue', 'blockEditingFromUI'];
|
|
11
15
|
const stringifyBooleans = (savedObject, keysToConvert) => {
|
|
12
|
-
|
|
16
|
+
const savedObjectKeySet = new Set(Object.keys(savedObject));
|
|
17
|
+
if (keysToConvert.every((key) => !savedObjectKeySet.has(key))) {
|
|
13
18
|
return savedObject;
|
|
14
19
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
return objectToReturn;
|
|
20
|
+
return {
|
|
21
|
+
...savedObject,
|
|
22
|
+
...Object.fromEntries(keysToConvert.map((key) => [key, typeof savedObject[key] === 'boolean' ? savedObject[key].toString() : savedObject[key]])),
|
|
23
|
+
};
|
|
22
24
|
};
|
|
23
25
|
const modelTableMapping = {
|
|
24
26
|
CustomFieldDefinition: {
|
|
@@ -29,6 +31,10 @@ const modelTableMapping = {
|
|
|
29
31
|
tableName: 'dim_custom_field_value',
|
|
30
32
|
eventVersion: '1',
|
|
31
33
|
},
|
|
34
|
+
CustomFieldEntries: {
|
|
35
|
+
tableName: 'dim_custom_field_entries',
|
|
36
|
+
eventVersion: '1',
|
|
37
|
+
},
|
|
32
38
|
};
|
|
33
39
|
const sendDimEvent = (instance) => {
|
|
34
40
|
const mapping = modelTableMapping[instance.constructor.name];
|
|
@@ -42,7 +48,7 @@ const sendDimEvent = (instance) => {
|
|
|
42
48
|
catch (err) {
|
|
43
49
|
logger_1.default.error('Failed to convert booleans in dim event payload', err);
|
|
44
50
|
}
|
|
45
|
-
events.sendObject(mapping.tableName, mapping.eventVersion, objectToSend);
|
|
51
|
+
events.sendObject(mapping.tableName, mapping.eventVersion, objectToSend).catch(() => { });
|
|
46
52
|
};
|
|
47
53
|
exports.sendDimEvent = sendDimEvent;
|
|
48
54
|
exports.default = events;
|
package/dist/hooks/create.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ModelOptions } from '../types';
|
|
1
|
+
import type { CustomFieldOptions, ModelOptions } from '../types';
|
|
2
2
|
/**
|
|
3
3
|
* A hook to create the custom fields when updating a model (more then one instance).
|
|
4
4
|
*/
|
|
@@ -7,4 +7,4 @@ export declare const beforeBulkCreate: (options: any) => void;
|
|
|
7
7
|
* A hook to create the custom fields when updating a model instance.
|
|
8
8
|
* TODO - cleanup if update fail
|
|
9
9
|
*/
|
|
10
|
-
export declare const beforeCreate: (scopeAttributes: string[], modelOptions?: ModelOptions) => (instance: any, options: any) => Promise<void>;
|
|
10
|
+
export declare const beforeCreate: (scopeAttributes: string[], modelOptions?: ModelOptions, sadotOptions?: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>) => (instance: any, options: any) => Promise<void>;
|
package/dist/hooks/create.js
CHANGED
|
@@ -28,10 +28,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.beforeCreate = exports.beforeBulkCreate = void 0;
|
|
30
30
|
const logger_1 = __importDefault(require("../utils/logger"));
|
|
31
|
-
const ValueRepo = __importStar(require("../repository/value"));
|
|
32
31
|
const DefinitionRepo = __importStar(require("../repository/definition"));
|
|
33
32
|
const errors_1 = require("../errors");
|
|
34
33
|
const scopeAttributes_1 = __importDefault(require("../utils/scopeAttributes"));
|
|
34
|
+
const updateInstanceValues_1 = __importDefault(require("./utils/updateInstanceValues"));
|
|
35
35
|
/**
|
|
36
36
|
* A hook to create the custom fields when updating a model (more then one instance).
|
|
37
37
|
*/
|
|
@@ -45,30 +45,51 @@ exports.beforeBulkCreate = beforeBulkCreate;
|
|
|
45
45
|
* A hook to create the custom fields when updating a model instance.
|
|
46
46
|
* TODO - cleanup if update fail
|
|
47
47
|
*/
|
|
48
|
-
const beforeCreate = (scopeAttributes, modelOptions = {}) => async (instance, options) => {
|
|
48
|
+
const beforeCreate = (scopeAttributes, modelOptions = {}, sadotOptions = { useCustomFieldsEntries: false }) => async (instance, options) => {
|
|
49
49
|
logger_1.default.debug('sadot - before create hook');
|
|
50
50
|
const { fields } = options;
|
|
51
|
+
const { include, useEntityIdFromInclude } = modelOptions;
|
|
51
52
|
const modelType = instance.constructor.name;
|
|
52
53
|
const identifiers = (0, scopeAttributes_1.default)(instance, scopeAttributes);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
await ValueRepo.updateValues(modelType, instance.id, identifiers, customFields, {
|
|
64
|
-
transaction: options.transaction,
|
|
65
|
-
modelOptions,
|
|
66
|
-
}, true);
|
|
54
|
+
const where = {
|
|
55
|
+
modelType,
|
|
56
|
+
disabled: false,
|
|
57
|
+
...(!useEntityIdFromInclude && { entityId: identifiers }),
|
|
58
|
+
};
|
|
59
|
+
const fieldDefinitions = await DefinitionRepo.findAll(where, { withDisabled: false, transaction: options.transaction, include: include?.(identifiers) });
|
|
60
|
+
const requiredFieldsNames = Array.from(new Set(fieldDefinitions.filter(({ required }) => required).map(({ name }) => name)));
|
|
61
|
+
const fieldsWithDefaultValue = fieldDefinitions.filter((def) => ![null, undefined].includes(def.defaultValue));
|
|
62
|
+
if (fieldsWithDefaultValue.length) {
|
|
67
63
|
// eslint-disable-next-line no-param-reassign
|
|
68
|
-
|
|
64
|
+
instance.customFields || (instance.customFields = {});
|
|
65
|
+
fieldsWithDefaultValue.filter((def) => (instance.customFields?.[def.name] === undefined)).forEach(({ name, defaultValue }) => {
|
|
66
|
+
// eslint-disable-next-line no-param-reassign
|
|
67
|
+
instance.customFields[name] = defaultValue;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const { customFields } = instance;
|
|
71
|
+
const fieldsNames = Object.keys(customFields ?? {});
|
|
72
|
+
const missingFields = requiredFieldsNames.filter((name) => !fieldsNames.includes(name));
|
|
73
|
+
if (missingFields?.length) {
|
|
74
|
+
throw new errors_1.MissingRequiredCustomFieldError(missingFields);
|
|
69
75
|
}
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
const customFieldsIdx = fields.indexOf('customFields');
|
|
77
|
+
if (customFieldsIdx === -1 || !customFields || !Object.keys(customFields).length) {
|
|
78
|
+
// After checking for required fields and fields with default values, and we have no custom fields.
|
|
79
|
+
return;
|
|
72
80
|
}
|
|
81
|
+
await (0, updateInstanceValues_1.default)({
|
|
82
|
+
modelId: instance.id,
|
|
83
|
+
modelType,
|
|
84
|
+
identifiers,
|
|
85
|
+
customFields,
|
|
86
|
+
options: {
|
|
87
|
+
useCustomFieldsEntries: sadotOptions.useCustomFieldsEntries,
|
|
88
|
+
transaction: options.transaction,
|
|
89
|
+
modelOptions,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
// eslint-disable-next-line no-param-reassign
|
|
93
|
+
fields.splice(customFieldsIdx, 1);
|
|
73
94
|
};
|
|
74
95
|
exports.beforeCreate = beforeCreate;
|