@autofleet/sadot 0.7.7-beta.0 → 0.7.7
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/dist/api/v1/definition/validations.js +2 -24
- package/dist/events/index.js +20 -21
- package/dist/hooks/create.js +1 -1
- package/dist/models/CustomFieldDefinition.d.ts +0 -1
- package/dist/models/CustomFieldDefinition.js +0 -14
- package/dist/models/index.js +1 -1
- package/dist/models/tests/contextAwareModels/ContextAwareTestModel.js +3 -1
- package/dist/repository/value.d.ts +1 -1
- package/dist/repository/value.js +7 -36
- package/dist/scopes/filter.d.ts +3 -10
- package/dist/scopes/filter.js +40 -33
- package/dist/tests/mocks/definition.mock.d.ts +0 -2
- package/dist/tests/mocks/definition.mock.js +9 -10
- package/dist/types/definition/index.d.ts +0 -1
- package/dist/utils/logger/index.d.ts +1 -1
- package/dist/utils/logger/index.js +3 -5
- package/package.json +1 -2
- package/src/hooks/create.ts +42 -24
- package/src/repository/definition.ts +15 -6
- package/src/repository/value.ts +4 -20
- package/src/scopes/filter.ts +20 -18
- package/coverage/clover.xml +0 -1073
- package/coverage/coverage-final.json +0 -44
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -461
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov-report/src/api/index.html +0 -116
- package/coverage/lcov-report/src/api/index.ts.html +0 -112
- package/coverage/lcov-report/src/api/v1/definition/index.html +0 -131
- package/coverage/lcov-report/src/api/v1/definition/index.ts.html +0 -406
- package/coverage/lcov-report/src/api/v1/definition/validations.ts.html +0 -310
- package/coverage/lcov-report/src/api/v1/errors.ts.html +0 -133
- package/coverage/lcov-report/src/api/v1/index.html +0 -131
- package/coverage/lcov-report/src/api/v1/index.ts.html +0 -112
- package/coverage/lcov-report/src/errors/index.html +0 -116
- package/coverage/lcov-report/src/errors/index.ts.html +0 -211
- package/coverage/lcov-report/src/events/index.html +0 -116
- package/coverage/lcov-report/src/events/index.ts.html +0 -238
- package/coverage/lcov-report/src/hooks/create.ts.html +0 -262
- package/coverage/lcov-report/src/hooks/enrich.ts.html +0 -523
- package/coverage/lcov-report/src/hooks/find.ts.html +0 -166
- package/coverage/lcov-report/src/hooks/index.html +0 -191
- package/coverage/lcov-report/src/hooks/index.ts.html +0 -130
- package/coverage/lcov-report/src/hooks/update.ts.html +0 -211
- package/coverage/lcov-report/src/hooks/workaround.ts.html +0 -226
- package/coverage/lcov-report/src/index.html +0 -116
- package/coverage/lcov-report/src/index.ts.html +0 -235
- package/coverage/lcov-report/src/models/CustomFieldDefinition.ts.html +0 -550
- package/coverage/lcov-report/src/models/CustomFieldValue.ts.html +0 -415
- package/coverage/lcov-report/src/models/index.html +0 -146
- package/coverage/lcov-report/src/models/index.ts.html +0 -406
- package/coverage/lcov-report/src/models/tests/AssociatedTestModel.ts.html +0 -256
- package/coverage/lcov-report/src/models/tests/TestModel.ts.html +0 -247
- package/coverage/lcov-report/src/models/tests/contextAwareModels/ContextAwareTestModel.ts.html +0 -214
- package/coverage/lcov-report/src/models/tests/contextAwareModels/ContextTestModel.ts.html +0 -199
- package/coverage/lcov-report/src/models/tests/contextAwareModels/index.html +0 -131
- package/coverage/lcov-report/src/models/tests/index.html +0 -131
- package/coverage/lcov-report/src/repository/definition.ts.html +0 -466
- package/coverage/lcov-report/src/repository/index.html +0 -131
- package/coverage/lcov-report/src/repository/value.ts.html +0 -523
- package/coverage/lcov-report/src/scopes/filter.ts.html +0 -637
- package/coverage/lcov-report/src/scopes/index.html +0 -131
- package/coverage/lcov-report/src/scopes/index.ts.html +0 -103
- package/coverage/lcov-report/src/tests/api/index.html +0 -116
- package/coverage/lcov-report/src/tests/api/test-api.ts.html +0 -199
- package/coverage/lcov-report/src/tests/functional/searching/index.html +0 -116
- package/coverage/lcov-report/src/tests/functional/searching/index.ts.html +0 -202
- package/coverage/lcov-report/src/tests/helpers/database-config.ts.html +0 -130
- package/coverage/lcov-report/src/tests/helpers/index.html +0 -131
- package/coverage/lcov-report/src/tests/helpers/index.ts.html +0 -142
- package/coverage/lcov-report/src/tests/mocks/definition.mock.ts.html +0 -310
- package/coverage/lcov-report/src/tests/mocks/events.mock.ts.html +0 -139
- package/coverage/lcov-report/src/tests/mocks/index.html +0 -146
- package/coverage/lcov-report/src/tests/mocks/testModel.ts.html +0 -196
- package/coverage/lcov-report/src/utils/constants/index.html +0 -116
- package/coverage/lcov-report/src/utils/constants/index.ts.html +0 -160
- package/coverage/lcov-report/src/utils/db/index.html +0 -116
- package/coverage/lcov-report/src/utils/db/index.ts.html +0 -148
- package/coverage/lcov-report/src/utils/helpers/index.html +0 -116
- package/coverage/lcov-report/src/utils/helpers/index.ts.html +0 -283
- package/coverage/lcov-report/src/utils/index.html +0 -131
- package/coverage/lcov-report/src/utils/init.ts.html +0 -430
- package/coverage/lcov-report/src/utils/logger/index.html +0 -116
- package/coverage/lcov-report/src/utils/logger/index.ts.html +0 -100
- package/coverage/lcov-report/src/utils/scopeAttributes.ts.html +0 -121
- package/coverage/lcov-report/src/utils/validations/index.html +0 -116
- package/coverage/lcov-report/src/utils/validations/index.ts.html +0 -151
- package/coverage/lcov-report/src/utils/validations/schema/custom-fields.ts.html +0 -109
- package/coverage/lcov-report/src/utils/validations/schema/index.html +0 -116
- package/coverage/lcov-report/src/utils/validations/validators/index.html +0 -146
- package/coverage/lcov-report/src/utils/validations/validators/index.ts.html +0 -199
- package/coverage/lcov-report/src/utils/validations/validators/select.validator.ts.html +0 -118
- package/coverage/lcov-report/src/utils/validations/validators/status.validator.ts.html +0 -139
- package/coverage/lcov.info +0 -1818
|
@@ -6,17 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.validateCustomFieldDefinitionUpdate = exports.validateCustomFieldDefinitionCreation = void 0;
|
|
7
7
|
const joi_1 = __importDefault(require("joi"));
|
|
8
8
|
const constants_1 = require("../../../utils/constants");
|
|
9
|
-
const
|
|
10
|
-
name: joi_1.default.string().required(),
|
|
11
|
-
type: joi_1.default.string(),
|
|
12
|
-
size: joi_1.default.string(),
|
|
13
|
-
addedBy: joi_1.default.string().uuid(),
|
|
14
|
-
});
|
|
15
|
-
const statusValidationObject = joi_1.default.object({
|
|
9
|
+
const statusValidationObjectSchema = joi_1.default.array().items(joi_1.default.object({
|
|
16
10
|
value: joi_1.default.string().required(),
|
|
17
11
|
color: joi_1.default.string().required(),
|
|
18
|
-
});
|
|
19
|
-
const statusValidationObjectSchema = joi_1.default.array().items(statusValidationObject).min(1).unique('value');
|
|
12
|
+
})).min(1).unique('value');
|
|
20
13
|
/**
|
|
21
14
|
* Schema for the validation of custom field definition
|
|
22
15
|
* The only custom validation is for
|
|
@@ -35,24 +28,10 @@ const ValidationSchema = joi_1.default.when('fieldType', {
|
|
|
35
28
|
then: statusValidationObjectSchema,
|
|
36
29
|
otherwise: joi_1.default.any(),
|
|
37
30
|
});
|
|
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: FileValidationSchema },
|
|
44
|
-
{ is: constants_1.CustomFieldDefinitionType.IMAGE, then: 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: statusValidationObject.allow(null) },
|
|
48
|
-
{ is: constants_1.CustomFieldDefinitionType.TEXT, then: joi_1.default.string().allow(null) },
|
|
49
|
-
],
|
|
50
|
-
});
|
|
51
31
|
const CustomFieldDefinitionCreationSchema = joi_1.default.object({
|
|
52
32
|
name: joi_1.default.string().required(),
|
|
53
33
|
displayName: joi_1.default.string().required(),
|
|
54
34
|
validation: ValidationSchema,
|
|
55
|
-
defaultValue: DefaultValueSchema,
|
|
56
35
|
fieldType: joi_1.default.string().valid(...Object.values(constants_1.CustomFieldDefinitionType)).required(),
|
|
57
36
|
entityId: joi_1.default.string().guid().required(),
|
|
58
37
|
entityType: joi_1.default.string().required(),
|
|
@@ -63,7 +42,6 @@ const CustomFieldDefinitionCreationSchema = joi_1.default.object({
|
|
|
63
42
|
const CustomFieldDefinitionUpdateSchema = joi_1.default.object({
|
|
64
43
|
displayName: joi_1.default.string(),
|
|
65
44
|
validation: ValidationSchema,
|
|
66
|
-
defaultValue: DefaultValueSchema,
|
|
67
45
|
fieldType: joi_1.default.string().valid(...Object.values(constants_1.CustomFieldDefinitionType)),
|
|
68
46
|
description: joi_1.default.string().allow(null),
|
|
69
47
|
required: joi_1.default.boolean(),
|
package/dist/events/index.js
CHANGED
|
@@ -7,18 +7,18 @@ exports.sendDimEvent = void 0;
|
|
|
7
7
|
const events_1 = __importDefault(require("@autofleet/events"));
|
|
8
8
|
const logger_1 = __importDefault(require("../utils/logger"));
|
|
9
9
|
const events = new events_1.default({ logger: logger_1.default });
|
|
10
|
-
const KEYS_TO_CONVERT = ['value'
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
13
|
-
|
|
10
|
+
const KEYS_TO_CONVERT = ['value'];
|
|
11
|
+
const stringifyBools = (savedObject, keysToConvert) => {
|
|
12
|
+
if (Object.keys(savedObject).some((key) => keysToConvert.includes(key))) {
|
|
13
|
+
const objectToReturn = { ...savedObject };
|
|
14
|
+
keysToConvert.forEach((key) => {
|
|
15
|
+
if (typeof savedObject[key] === 'boolean') {
|
|
16
|
+
objectToReturn[key] = savedObject[key].toString();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return objectToReturn;
|
|
14
20
|
}
|
|
15
|
-
|
|
16
|
-
keysToConvert.forEach((key) => {
|
|
17
|
-
if (typeof savedObject[key] === 'boolean') {
|
|
18
|
-
objectToReturn[key] = savedObject[key].toString();
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
return objectToReturn;
|
|
21
|
+
return savedObject;
|
|
22
22
|
};
|
|
23
23
|
const modelTableMapping = {
|
|
24
24
|
CustomFieldDefinition: {
|
|
@@ -32,17 +32,16 @@ const modelTableMapping = {
|
|
|
32
32
|
};
|
|
33
33
|
const sendDimEvent = (instance) => {
|
|
34
34
|
const mapping = modelTableMapping[instance.constructor.name];
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
if (mapping) {
|
|
36
|
+
let objectToSend = instance.get();
|
|
37
|
+
try {
|
|
38
|
+
objectToSend = stringifyBools(instance.get(), KEYS_TO_CONVERT);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
logger_1.default.error('Failed to convert booleans in dim event payload', err);
|
|
42
|
+
}
|
|
43
|
+
events.sendObject(mapping.tableName, mapping.eventVersion, objectToSend);
|
|
44
44
|
}
|
|
45
|
-
events.sendObject(mapping.tableName, mapping.eventVersion, objectToSend);
|
|
46
45
|
};
|
|
47
46
|
exports.sendDimEvent = sendDimEvent;
|
|
48
47
|
exports.default = events;
|
package/dist/hooks/create.js
CHANGED
|
@@ -63,7 +63,7 @@ const beforeCreate = (scopeAttributes, modelOptions = {}) => async (instance, op
|
|
|
63
63
|
await ValueRepo.updateValues(modelType, instance.id, identifiers, customFields, {
|
|
64
64
|
transaction: options.transaction,
|
|
65
65
|
modelOptions,
|
|
66
|
-
}
|
|
66
|
+
});
|
|
67
67
|
// eslint-disable-next-line no-param-reassign
|
|
68
68
|
fields.splice(customFieldsIdx, 1);
|
|
69
69
|
}
|
|
@@ -19,19 +19,12 @@ const _1 = require(".");
|
|
|
19
19
|
const events_1 = require("../events");
|
|
20
20
|
const errors_1 = require("../errors");
|
|
21
21
|
const logger_1 = __importDefault(require("../utils/logger"));
|
|
22
|
-
const validations_1 = require("../utils/validations");
|
|
23
22
|
let CustomFieldDefinition = class CustomFieldDefinition extends sequelize_typescript_1.Model {
|
|
24
23
|
static displayNameDefaultValue(instance) {
|
|
25
24
|
if (!instance?.displayName) {
|
|
26
25
|
// eslint-disable-next-line no-param-reassign
|
|
27
26
|
instance.displayName = instance.name;
|
|
28
27
|
}
|
|
29
|
-
if (![null, undefined].includes(instance.defaultValue)) {
|
|
30
|
-
const isValid = (0, validations_1.validateValue)(instance.defaultValue, instance.fieldType, instance.validation);
|
|
31
|
-
if (!isValid) {
|
|
32
|
-
throw new errors_1.InvalidValueError(instance.defaultValue, instance.fieldType);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
28
|
}
|
|
36
29
|
static afterSaveHandler(instance, options) {
|
|
37
30
|
if (options.transaction) {
|
|
@@ -123,13 +116,6 @@ __decorate([
|
|
|
123
116
|
}),
|
|
124
117
|
__metadata("design:type", Boolean)
|
|
125
118
|
], CustomFieldDefinition.prototype, "disabled", void 0);
|
|
126
|
-
__decorate([
|
|
127
|
-
(0, sequelize_typescript_1.Column)({
|
|
128
|
-
type: sequelize_typescript_1.DataType.JSONB,
|
|
129
|
-
allowNull: true,
|
|
130
|
-
}),
|
|
131
|
-
__metadata("design:type", Object)
|
|
132
|
-
], CustomFieldDefinition.prototype, "defaultValue", void 0);
|
|
133
119
|
__decorate([
|
|
134
120
|
sequelize_typescript_1.Column,
|
|
135
121
|
__metadata("design:type", Date)
|
package/dist/models/index.js
CHANGED
|
@@ -22,7 +22,7 @@ exports.AssociatedTestModel = AssociatedTestModel_1.default;
|
|
|
22
22
|
const productionModels = [CustomFieldDefinition_1.default, CustomFieldValue_1.default];
|
|
23
23
|
const testModels = [TestModel_1.default, AssociatedTestModel_1.default, ContextAwareTestModel_1.default, ContextTestModel_1.default];
|
|
24
24
|
const SADOT_MIGRATION_PREFIX = 'sadot-migration';
|
|
25
|
-
const SCHEMA_VERSION =
|
|
25
|
+
const SCHEMA_VERSION = 1;
|
|
26
26
|
const CUSTOM_FIELDS_SCHEMA_VERSION = `${SADOT_MIGRATION_PREFIX}_${SCHEMA_VERSION}`;
|
|
27
27
|
const initTables = async (sequelize, getUser) => {
|
|
28
28
|
logger_1.default.info('custom-fields: initialize custom-fields tables');
|
|
@@ -28,7 +28,9 @@ __decorate([
|
|
|
28
28
|
], ContextAwareTestModel.prototype, "id", void 0);
|
|
29
29
|
__decorate([
|
|
30
30
|
(0, sequelize_typescript_1.ForeignKey)(() => ContextTestModel_1.default),
|
|
31
|
-
(0, sequelize_typescript_1.Column)({
|
|
31
|
+
(0, sequelize_typescript_1.Column)({
|
|
32
|
+
type: sequelize_typescript_1.DataType.UUID,
|
|
33
|
+
}),
|
|
32
34
|
__metadata("design:type", String)
|
|
33
35
|
], ContextAwareTestModel.prototype, "contextId", void 0);
|
|
34
36
|
__decorate([
|
|
@@ -24,5 +24,5 @@ export declare const findValuesByModelIds: (modelIds: string[], options?: any) =
|
|
|
24
24
|
*/
|
|
25
25
|
export declare const updateValues: (modelType: string, modelId: string, identifiers: string[], valuesToUpdate: ValuesToUpdate, options?: FindOptions & {
|
|
26
26
|
modelOptions?: ModelOptions;
|
|
27
|
-
}
|
|
27
|
+
}) => Promise<CustomFieldValue[]>;
|
|
28
28
|
export declare const deleteValue: (id: string, options?: any) => Promise<any>;
|
package/dist/repository/value.js
CHANGED
|
@@ -31,7 +31,6 @@ const models_1 = require("../models");
|
|
|
31
31
|
const DefinitionRepo = __importStar(require("./definition"));
|
|
32
32
|
const logger_1 = __importDefault(require("../utils/logger"));
|
|
33
33
|
const errors_1 = require("../errors");
|
|
34
|
-
const constants_1 = require("../utils/constants");
|
|
35
34
|
const findByModelIdAndDefinition = async (modelId, customFieldDefinitionId) => models_1.CustomFieldValue.findAll({ where: { modelId, customFieldDefinitionId }, include: [models_1.CustomFieldDefinition] });
|
|
36
35
|
exports.findByModelIdAndDefinition = findByModelIdAndDefinition;
|
|
37
36
|
const create = async (data, withAssociations = false) => {
|
|
@@ -67,24 +66,12 @@ const findValuesByModelIds = async (modelIds, options) => {
|
|
|
67
66
|
});
|
|
68
67
|
};
|
|
69
68
|
exports.findValuesByModelIds = findValuesByModelIds;
|
|
70
|
-
const formatFunctions = {
|
|
71
|
-
[constants_1.CustomFieldDefinitionType.DATE]: (value) => {
|
|
72
|
-
if (value) {
|
|
73
|
-
const date = new Date(value);
|
|
74
|
-
if (date.toString() === 'Invalid Date') {
|
|
75
|
-
throw new Error(`Invalid date value: ${value}`);
|
|
76
|
-
}
|
|
77
|
-
return date.toISOString();
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
69
|
/**
|
|
83
70
|
* Try to update custom field values for a model instance.
|
|
84
71
|
* Create new value record if not exists, but fails if value's definition not exist.
|
|
85
72
|
* Return the updated values
|
|
86
73
|
*/
|
|
87
|
-
const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, options = {}
|
|
74
|
+
const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, options = {}) => {
|
|
88
75
|
const names = Object.keys(valuesToUpdate);
|
|
89
76
|
logger_1.default.debug(`custom-fields: updating values for ${modelType} ${modelId}`, {
|
|
90
77
|
names,
|
|
@@ -112,28 +99,12 @@ const updateValues = async (modelType, modelId, identifiers, valuesToUpdate, opt
|
|
|
112
99
|
if (valuesWithDisabledDefinitions?.length > 0) {
|
|
113
100
|
logger_1.default.warn(`custom-fields: trying to update disabled values: ${valuesWithDisabledDefinitions.join(', ')}`);
|
|
114
101
|
}
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
modelId,
|
|
122
|
-
value: (formatFunction ? formatFunction(valuesToUpdate[name]) : valuesToUpdate[name]) ?? fieldDefinition.defaultValue,
|
|
123
|
-
updatedAt: new Date(),
|
|
124
|
-
customFieldDefinitionId: fieldDefinition.id,
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
if (defineAllDefaults) {
|
|
128
|
-
fieldDefinitions.filter((def) => !visitedFields.has(def) && ![null, undefined].includes(def.defaultValue)).forEach(({ id, defaultValue }) => {
|
|
129
|
-
values.push({
|
|
130
|
-
modelId,
|
|
131
|
-
value: defaultValue,
|
|
132
|
-
updatedAt: new Date(),
|
|
133
|
-
customFieldDefinitionId: id,
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
}
|
|
102
|
+
const values = names.map((name) => ({
|
|
103
|
+
modelId,
|
|
104
|
+
value: valuesToUpdate[name],
|
|
105
|
+
updatedAt: new Date(),
|
|
106
|
+
customFieldDefinitionId: fieldDefinitions.find((def) => def.name === name).id,
|
|
107
|
+
}));
|
|
137
108
|
return Promise.all(values.map(async (value) => {
|
|
138
109
|
const [cfv] = await models_1.CustomFieldValue.upsert(value, {
|
|
139
110
|
transaction: options.transaction,
|
package/dist/scopes/filter.d.ts
CHANGED
|
@@ -17,10 +17,6 @@ export type CustomFieldFilterOptions = {
|
|
|
17
17
|
where?: WhereOptions;
|
|
18
18
|
replacements?: Record<string, string>;
|
|
19
19
|
};
|
|
20
|
-
type customFieldsFilterScopeParams = {
|
|
21
|
-
replacementsMap: Record<string, string>;
|
|
22
|
-
scopeValue: Record<string, ConditionValue>;
|
|
23
|
-
};
|
|
24
20
|
/**
|
|
25
21
|
* A Sequelize scope for filtering models by custom fields.
|
|
26
22
|
* This scope builds a WHERE clause to be applied on the main query.
|
|
@@ -28,12 +24,9 @@ type customFieldsFilterScopeParams = {
|
|
|
28
24
|
* @param name - The model type name used to join custom_field_definitions.
|
|
29
25
|
* @returns A function that takes conditions and returns the Sequelize options object.
|
|
30
26
|
*/
|
|
31
|
-
export declare const customFieldsFilterScope: (name: string) => (
|
|
27
|
+
export declare const customFieldsFilterScope: (name: string) => (conditions: Record<string, ConditionValue>) => CustomFieldFilterOptions;
|
|
32
28
|
export declare const scopeName = "filterByCustomFields";
|
|
33
|
-
export declare const customFieldsSortScope: (name: string) => (
|
|
34
|
-
replacementsMap: any;
|
|
35
|
-
scopeValue: any;
|
|
36
|
-
}) => {
|
|
29
|
+
export declare const customFieldsSortScope: (name: string) => (sort: CustomFieldSort[]) => {
|
|
37
30
|
attributes?: undefined;
|
|
38
31
|
order?: undefined;
|
|
39
32
|
replacements?: undefined;
|
|
@@ -42,6 +35,6 @@ export declare const customFieldsSortScope: (name: string) => ({ replacementsMap
|
|
|
42
35
|
include: (string | import("sequelize/types/utils").Literal)[][];
|
|
43
36
|
};
|
|
44
37
|
order: import("sequelize/types/utils").Literal[];
|
|
45
|
-
replacements:
|
|
38
|
+
replacements: Record<string, string>;
|
|
46
39
|
};
|
|
47
40
|
export {};
|
package/dist/scopes/filter.js
CHANGED
|
@@ -8,12 +8,11 @@ exports.customFieldsSortScope = exports.scopeName = exports.customFieldsFilterSc
|
|
|
8
8
|
const sequelize_1 = require("sequelize");
|
|
9
9
|
const sequelize_typescript_1 = require("sequelize-typescript");
|
|
10
10
|
const common_types_1 = require("@autofleet/common-types");
|
|
11
|
+
const moment_1 = __importDefault(require("moment"));
|
|
11
12
|
const helpers_1 = require("../utils/helpers");
|
|
12
|
-
const logger_1 = __importDefault(require("../utils/logger"));
|
|
13
13
|
const { CUSTOM_FIELDS_FILTER_SCOPE } = common_types_1.customFields;
|
|
14
|
-
const isDate = (input) => input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
|
|
15
14
|
const castIfNeeded = (conditionValue) => {
|
|
16
|
-
if (isDate(conditionValue)) {
|
|
15
|
+
if (moment_1.default.isDate(conditionValue)) {
|
|
17
16
|
return '::timestamp';
|
|
18
17
|
}
|
|
19
18
|
if (!Number.isNaN(Number(conditionValue))) {
|
|
@@ -26,7 +25,8 @@ const OR_DELIMETER = ' OR ';
|
|
|
26
25
|
const CD_TABLE_ALIAS = 'cd';
|
|
27
26
|
const CD_NAME_COLUMN = `${CD_TABLE_ALIAS}.name`;
|
|
28
27
|
const CV_TABLE_ALIAS = 'cv';
|
|
29
|
-
const CV_VALUE_COLUMN = `(${CV_TABLE_ALIAS}.value
|
|
28
|
+
const CV_VALUE_COLUMN = `(${CV_TABLE_ALIAS}.value)`;
|
|
29
|
+
const castValueToJsonb = (value) => `to_jsonb(${value}::text)`;
|
|
30
30
|
/**
|
|
31
31
|
* A Sequelize scope for filtering models by custom fields.
|
|
32
32
|
* This scope builds a WHERE clause to be applied on the main query.
|
|
@@ -34,16 +34,18 @@ const CV_VALUE_COLUMN = `(${CV_TABLE_ALIAS}.value::varchar)`;
|
|
|
34
34
|
* @param name - The model type name used to join custom_field_definitions.
|
|
35
35
|
* @returns A function that takes conditions and returns the Sequelize options object.
|
|
36
36
|
*/
|
|
37
|
-
const customFieldsFilterScope = (name) => (
|
|
37
|
+
const customFieldsFilterScope = (name) => (conditions) => {
|
|
38
38
|
if (!conditions || Object.keys(conditions).length === 0) {
|
|
39
39
|
return {};
|
|
40
40
|
}
|
|
41
|
+
const ConditionNameRandomStr = (0, helpers_1.generateRandomString)();
|
|
42
|
+
const replacements = {};
|
|
43
|
+
replacements[ConditionNameRandomStr] = `${name}`;
|
|
41
44
|
// Build the WHERE clause for custom field filtering
|
|
42
45
|
const conditionsStrings = Object.entries(conditions)
|
|
43
46
|
.map(([key, condition]) => {
|
|
44
|
-
const replacemetKey =
|
|
45
|
-
|
|
46
|
-
return false;
|
|
47
|
+
const replacemetKey = (0, helpers_1.generateRandomString)();
|
|
48
|
+
replacements[replacemetKey] = `${key}`;
|
|
47
49
|
const columnCondition = `(${CD_NAME_COLUMN} = :${replacemetKey})`;
|
|
48
50
|
if (Array.isArray(condition)) {
|
|
49
51
|
if (condition.length === 0) {
|
|
@@ -52,24 +54,31 @@ const customFieldsFilterScope = (name) => ({ replacementsMap: replacements, scop
|
|
|
52
54
|
}
|
|
53
55
|
if (typeof condition[0] === 'string') {
|
|
54
56
|
const values = condition.map((v) => {
|
|
55
|
-
const valRandom =
|
|
56
|
-
|
|
57
|
+
const valRandom = (0, helpers_1.generateRandomString)();
|
|
58
|
+
replacements[`${valRandom}`] = `${v}`;
|
|
59
|
+
return castValueToJsonb(`:${valRandom}`);
|
|
57
60
|
}).join(',');
|
|
58
61
|
return `(${columnCondition} AND ${CV_VALUE_COLUMN} IN ( ${values} ))`;
|
|
59
62
|
}
|
|
60
63
|
return condition
|
|
61
64
|
.map((c) => {
|
|
62
|
-
const valRep =
|
|
63
|
-
|
|
65
|
+
const valRep = (0, helpers_1.generateRandomString)();
|
|
66
|
+
replacements[valRep] = `${c.value}`;
|
|
67
|
+
const valueAsJsonb = castValueToJsonb(`:${valRep}`);
|
|
68
|
+
return `(${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(c.value)} ${c.operator} ${valueAsJsonb})`;
|
|
64
69
|
}).join(AND_DELIMETER);
|
|
65
70
|
}
|
|
66
71
|
if (typeof condition === 'string' || typeof condition === 'number') {
|
|
67
|
-
const conditionRep =
|
|
68
|
-
|
|
72
|
+
const conditionRep = (0, helpers_1.generateRandomString)();
|
|
73
|
+
replacements[conditionRep] = `${condition}`;
|
|
74
|
+
const valueAsJsonb = castValueToJsonb(`:${conditionRep}`);
|
|
75
|
+
return `(${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition)} = ${valueAsJsonb})`;
|
|
69
76
|
}
|
|
70
77
|
if (condition?.operator) {
|
|
71
|
-
const valueRep =
|
|
72
|
-
|
|
78
|
+
const valueRep = (0, helpers_1.generateRandomString)();
|
|
79
|
+
replacements[valueRep] = `${condition.value}`;
|
|
80
|
+
const valueAsJsonb = castValueToJsonb(`:${valueRep}`);
|
|
81
|
+
return `( ${columnCondition} AND ${CV_VALUE_COLUMN}${castIfNeeded(condition.value)} ${condition.operator} ${valueAsJsonb})`;
|
|
73
82
|
}
|
|
74
83
|
return false;
|
|
75
84
|
})
|
|
@@ -79,15 +88,14 @@ const customFieldsFilterScope = (name) => ({ replacementsMap: replacements, scop
|
|
|
79
88
|
}
|
|
80
89
|
const customFieldConditions = conditionsStrings.join(OR_DELIMETER);
|
|
81
90
|
const subQuery = `
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`.replace(/\n/g, '');
|
|
90
|
-
logger_1.default.info('custom fields filter scope', { subQuery, replacements });
|
|
91
|
+
SELECT cv.model_id
|
|
92
|
+
FROM custom_field_values AS cv
|
|
93
|
+
INNER JOIN custom_field_definitions AS cd ON cv.custom_field_definition_id = cd.id
|
|
94
|
+
AND cd.model_type = :${ConditionNameRandomStr}
|
|
95
|
+
WHERE ${customFieldConditions}
|
|
96
|
+
GROUP BY cv.model_id
|
|
97
|
+
HAVING COUNT(DISTINCT cv.custom_field_definition_id) = ${conditionsStrings.length}
|
|
98
|
+
`.replace(/\n/g, '');
|
|
91
99
|
return {
|
|
92
100
|
where: {
|
|
93
101
|
id: {
|
|
@@ -99,13 +107,15 @@ const customFieldsFilterScope = (name) => ({ replacementsMap: replacements, scop
|
|
|
99
107
|
};
|
|
100
108
|
exports.customFieldsFilterScope = customFieldsFilterScope;
|
|
101
109
|
exports.scopeName = CUSTOM_FIELDS_FILTER_SCOPE;
|
|
102
|
-
const customFieldsSortScope = (name) => (
|
|
110
|
+
const customFieldsSortScope = (name) => (sort) => {
|
|
103
111
|
if (!sort || sort.length === 0) {
|
|
104
112
|
return {};
|
|
105
113
|
}
|
|
106
114
|
const randomStr = (0, helpers_1.generateRandomString)();
|
|
115
|
+
const replacements = {};
|
|
107
116
|
const includes = Object.entries(sort).map(([key]) => {
|
|
108
|
-
const
|
|
117
|
+
const keyRandomReplacement = (0, helpers_1.generateRandomString)();
|
|
118
|
+
replacements[keyRandomReplacement] = `${key}`;
|
|
109
119
|
return ([
|
|
110
120
|
sequelize_typescript_1.Sequelize.literal(`(
|
|
111
121
|
SELECT value
|
|
@@ -114,22 +124,19 @@ const customFieldsSortScope = (name) => ({ replacementsMap, scopeValue: sort })
|
|
|
114
124
|
ON cv.custom_field_definition_id = cd.id
|
|
115
125
|
AND cd.model_type = '${name}'
|
|
116
126
|
WHERE cv.model_id = "${name}"."id"
|
|
117
|
-
AND cd.name = :${
|
|
127
|
+
AND cd.name = :${keyRandomReplacement}
|
|
118
128
|
) AS CustomFieldAggregation
|
|
119
129
|
)
|
|
120
130
|
`), randomStr,
|
|
121
131
|
]);
|
|
122
132
|
});
|
|
123
|
-
const orders = Object.entries(sort).map(([,
|
|
124
|
-
const direction = typeof sortObject === 'string' ? sortObject : Object.values(sortObject)[0];
|
|
125
|
-
return sequelize_typescript_1.Sequelize.literal(`"${randomStr}" ${direction || 'ASC'}`);
|
|
126
|
-
});
|
|
133
|
+
const orders = Object.entries(sort).map(([, value]) => sequelize_typescript_1.Sequelize.literal(`"${randomStr}" ${value}`));
|
|
127
134
|
return {
|
|
128
135
|
attributes: {
|
|
129
136
|
include: includes,
|
|
130
137
|
},
|
|
131
138
|
order: orders,
|
|
132
|
-
replacements
|
|
139
|
+
replacements,
|
|
133
140
|
};
|
|
134
141
|
};
|
|
135
142
|
exports.customFieldsSortScope = customFieldsSortScope;
|
|
@@ -14,7 +14,6 @@ export declare const coolFieldDefinition2: {
|
|
|
14
14
|
createdAt?: Date;
|
|
15
15
|
updatedAt?: Date;
|
|
16
16
|
deletedAt?: Date;
|
|
17
|
-
defaultValue?: any;
|
|
18
17
|
displayName?: string;
|
|
19
18
|
validation?: any;
|
|
20
19
|
fieldType: string;
|
|
@@ -30,7 +29,6 @@ export declare const coolFieldDefinition3: {
|
|
|
30
29
|
createdAt?: Date;
|
|
31
30
|
updatedAt?: Date;
|
|
32
31
|
deletedAt?: Date;
|
|
33
|
-
defaultValue?: any;
|
|
34
32
|
displayName?: string;
|
|
35
33
|
validation?: any;
|
|
36
34
|
fieldType: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createDefinitions = exports.createDefinition = exports.statusField = exports.selectField = exports.booleanField = exports.coolFieldDefinition3 = exports.coolFieldDefinition2 = exports.coolFieldDefinition = exports.contextAwareFieldDefinition = void 0;
|
|
4
|
-
const
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
5
|
exports.contextAwareFieldDefinition = {
|
|
6
6
|
name: 'cool field',
|
|
7
7
|
modelType: 'ContextAwareTestModel',
|
|
@@ -12,7 +12,7 @@ exports.coolFieldDefinition = {
|
|
|
12
12
|
name: 'cool field',
|
|
13
13
|
modelType: 'TestModel',
|
|
14
14
|
fieldType: 'number',
|
|
15
|
-
entityId: (0,
|
|
15
|
+
entityId: (0, uuid_1.v4)(),
|
|
16
16
|
entityType: 'fleetId',
|
|
17
17
|
};
|
|
18
18
|
exports.coolFieldDefinition2 = {
|
|
@@ -27,7 +27,7 @@ const booleanField = (modelType) => ({
|
|
|
27
27
|
name: 'shapeless',
|
|
28
28
|
modelType,
|
|
29
29
|
fieldType: 'boolean',
|
|
30
|
-
entityId: (0,
|
|
30
|
+
entityId: (0, uuid_1.v4)(),
|
|
31
31
|
entityType: 'fleetId',
|
|
32
32
|
});
|
|
33
33
|
exports.booleanField = booleanField;
|
|
@@ -36,7 +36,7 @@ const selectField = (modelType, options) => ({
|
|
|
36
36
|
modelType,
|
|
37
37
|
fieldType: 'select',
|
|
38
38
|
validation: options,
|
|
39
|
-
entityId: (0,
|
|
39
|
+
entityId: (0, uuid_1.v4)(),
|
|
40
40
|
entityType: 'fleetId',
|
|
41
41
|
});
|
|
42
42
|
exports.selectField = selectField;
|
|
@@ -45,25 +45,24 @@ const statusField = (modelType, options) => ({
|
|
|
45
45
|
modelType,
|
|
46
46
|
fieldType: 'status',
|
|
47
47
|
validation: options,
|
|
48
|
-
entityId: (0,
|
|
48
|
+
entityId: (0, uuid_1.v4)(),
|
|
49
49
|
entityType: 'fleetId',
|
|
50
50
|
});
|
|
51
51
|
exports.statusField = statusField;
|
|
52
52
|
// eslint-disable-next-line max-len
|
|
53
53
|
const createDefinition = (defaults) => ({
|
|
54
|
-
name: defaults?.name || `def_${(0,
|
|
54
|
+
name: defaults?.name || `def_${(0, uuid_1.v4)()}`,
|
|
55
55
|
modelType: defaults?.modelType || 'TestModel',
|
|
56
56
|
fieldType: defaults?.fieldType || 'boolean',
|
|
57
|
-
entityId: defaults?.entityId || (0,
|
|
57
|
+
entityId: defaults?.entityId || (0, uuid_1.v4)(),
|
|
58
58
|
entityType: defaults?.entityType || 'fleetId',
|
|
59
|
-
...(defaults?.defaultValue && { defaultValue: defaults.defaultValue }),
|
|
60
59
|
});
|
|
61
60
|
exports.createDefinition = createDefinition;
|
|
62
61
|
const createDefinitions = (defaults, length = 1) => (Array(length).fill({}).map((_) => ({
|
|
63
|
-
name: defaults?.name || `def_${(0,
|
|
62
|
+
name: defaults?.name || `def_${(0, uuid_1.v4)()}`,
|
|
64
63
|
modelType: defaults?.modelType || 'TestModel',
|
|
65
64
|
fieldType: defaults?.fieldType || 'boolean',
|
|
66
|
-
entityId: defaults?.entityId || (0,
|
|
65
|
+
entityId: defaults?.entityId || (0, uuid_1.v4)(),
|
|
67
66
|
entityType: defaults?.entityType || 'fleetId',
|
|
68
67
|
})));
|
|
69
68
|
exports.createDefinitions = createDefinitions;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const logger:
|
|
1
|
+
declare const logger: any;
|
|
2
2
|
export default logger;
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
const
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
4
|
+
const Logger = require('@autofleet/logger');
|
|
5
|
+
const logger = Logger();
|
|
8
6
|
exports.default = logger;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/sadot",
|
|
3
|
-
"version": "0.7.7
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
"build": "rm -rf dist && tsc",
|
|
9
9
|
"linter": "eslint .",
|
|
10
10
|
"test": "jest --forceExit --runInBand",
|
|
11
|
-
"test-debug": "node --inspect-brk node_modules/.bin/jest --runInBand --testTimeout=10000000",
|
|
12
11
|
"coverage": "jest --coverage --forceExit --runInBand && rm -rf ./coverage",
|
|
13
12
|
"build-to-local-repo": "node --run build && cp -r dist/* ../$REPO/node_modules/$npm_package_name/dist",
|
|
14
13
|
"dev": "nodemon",
|