@autofleet/sadot 0.13.5-beta.0 → 0.13.5
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/utils/helpers/index.d.ts +4 -3
- package/dist/utils/helpers/index.js +22 -30
- package/dist/utils/init.js +4 -2
- package/package.json +1 -1
- package/src/utils/helpers/index.ts +28 -35
- package/src/utils/init.ts +3 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type WhereOptions, type
|
|
1
|
+
import { type WhereOptions, type BindOrReplacements } from 'sequelize';
|
|
2
2
|
import { type ModelStatic } from 'sequelize-typescript';
|
|
3
3
|
import { CustomFieldDefinitionType } from '../constants';
|
|
4
4
|
/**
|
|
@@ -14,11 +14,12 @@ import { CustomFieldDefinitionType } from '../constants';
|
|
|
14
14
|
* @param {CustomFieldDefinitionType[]} excludedCustomFieldsTypes - An array of custom field types
|
|
15
15
|
* to exclude from the search
|
|
16
16
|
*
|
|
17
|
-
* @returns {CustomFieldsSearchPayload} - An object containing the
|
|
17
|
+
* @returns {CustomFieldsSearchPayload} - An object containing the WHERE clause and replacements
|
|
18
|
+
* for Sequelize.
|
|
18
19
|
*/
|
|
19
20
|
interface CustomFieldsSearchPayload {
|
|
20
21
|
where: WhereOptions;
|
|
21
|
-
|
|
22
|
+
replacements: BindOrReplacements;
|
|
22
23
|
}
|
|
23
24
|
export declare const generateRandomString: (length?: number) => string;
|
|
24
25
|
export declare const generateCustomFieldSearchQueryPayload: (searchTerm: string, model: ModelStatic, entityId: string, customFieldsTypesToExclude?: CustomFieldDefinitionType[]) => CustomFieldsSearchPayload;
|
|
@@ -6,7 +6,6 @@ const sequelize_1 = require("sequelize");
|
|
|
6
6
|
const sequelize_typescript_1 = require("sequelize-typescript");
|
|
7
7
|
const node_crypto_1 = require("node:crypto");
|
|
8
8
|
const constants_1 = require("../constants");
|
|
9
|
-
const models_1 = require("../../models");
|
|
10
9
|
const generateRandomString = (length = 5) => {
|
|
11
10
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
12
11
|
return Array.from({ length }, () => characters.charAt((0, node_crypto_1.randomInt)(characters.length))).join('');
|
|
@@ -15,34 +14,27 @@ exports.generateRandomString = generateRandomString;
|
|
|
15
14
|
const generateCustomFieldSearchQueryPayload = (searchTerm, model, entityId, customFieldsTypesToExclude = [
|
|
16
15
|
constants_1.CustomFieldDefinitionType.DATETIME,
|
|
17
16
|
constants_1.CustomFieldDefinitionType.DATE,
|
|
18
|
-
]) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
where: {
|
|
37
|
-
deleted_at: null,
|
|
38
|
-
},
|
|
39
|
-
},
|
|
17
|
+
]) => {
|
|
18
|
+
const excludedTypesString = customFieldsTypesToExclude.map((type) => `'${type}'`).join(',');
|
|
19
|
+
const subQuery = 'EXISTS ('
|
|
20
|
+
+ ' SELECT 1'
|
|
21
|
+
+ ' FROM "custom_field_values" AS "cv"'
|
|
22
|
+
+ ' INNER JOIN custom_field_definitions AS cd '
|
|
23
|
+
+ ` ON cd.entity_id = '${entityId}'`
|
|
24
|
+
+ ' AND cv.custom_field_definition_id = cd.id'
|
|
25
|
+
+ ` AND cd.model_type = '${model.name}'`
|
|
26
|
+
+ ` ${excludedTypesString ? `AND cd.field_type NOT IN (${excludedTypesString})` : ''}`
|
|
27
|
+
+ ' WHERE'
|
|
28
|
+
+ ' "cv"."deleted_at" IS NULL'
|
|
29
|
+
+ ` AND "cv"."model_id" = "${model.name}"."id"`
|
|
30
|
+
+ ' AND CAST("cv"."value" AS TEXT) ILIKE :searchTerm)';
|
|
31
|
+
return {
|
|
32
|
+
where: {
|
|
33
|
+
[sequelize_1.Op.or]: [
|
|
34
|
+
sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.literal(subQuery), true),
|
|
40
35
|
],
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}],
|
|
46
|
-
where: sequelize_typescript_1.Sequelize.where(sequelize_typescript_1.Sequelize.col('customFieldValue.model_id'), { [sequelize_1.Op.not]: null }),
|
|
47
|
-
});
|
|
36
|
+
},
|
|
37
|
+
replacements: { searchTerm: `%${searchTerm}%` },
|
|
38
|
+
};
|
|
39
|
+
};
|
|
48
40
|
exports.generateCustomFieldSearchQueryPayload = generateCustomFieldSearchQueryPayload;
|
package/dist/utils/init.js
CHANGED
|
@@ -73,7 +73,9 @@ exports.removeHooks = removeHooks;
|
|
|
73
73
|
/**
|
|
74
74
|
* Necessary associations for the {@link customFieldsFilterScope} scope
|
|
75
75
|
*/
|
|
76
|
-
const addAssociations = (model, modelName) => {
|
|
76
|
+
const addAssociations = (model, modelName, options) => {
|
|
77
|
+
if (options?.useCustomFieldsEntries)
|
|
78
|
+
return;
|
|
77
79
|
model.hasMany(models_1.CustomFieldValue, { foreignKey: 'modelId', as: 'customFieldValue' });
|
|
78
80
|
// TBC: maybe can be removed
|
|
79
81
|
models_1.CustomFieldValue.belongsTo(model, { foreignKey: 'modelId', as: modelName });
|
|
@@ -90,7 +92,7 @@ const addScopes = (models, getModel, options = { useCustomFieldsEntries: false }
|
|
|
90
92
|
return;
|
|
91
93
|
}
|
|
92
94
|
// Necessary associations for the filtering scope
|
|
93
|
-
addAssociations(model, name);
|
|
95
|
+
addAssociations(model, name, options);
|
|
94
96
|
// Add filter scope
|
|
95
97
|
model.addScope(CUSTOM_FIELDS_FILTER_SCOPE, (0, scopes_1.customFieldsFilterScope)(name, options));
|
|
96
98
|
model.addScope(custom_fields_1.CUSTOM_FIELDS_SORT_SCOPE, (0, filter_1.customFieldsSortScope)(name, options));
|
package/package.json
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
/* eslint-disable import/prefer-default-export */
|
|
2
|
-
import {
|
|
3
|
-
type WhereOptions, Op, type IncludeOptions,
|
|
4
|
-
} from 'sequelize';
|
|
2
|
+
import { type WhereOptions, Op, type BindOrReplacements } from 'sequelize';
|
|
5
3
|
import { type ModelStatic, Sequelize } from 'sequelize-typescript';
|
|
6
4
|
import { randomInt } from 'node:crypto';
|
|
7
5
|
import { CustomFieldDefinitionType } from '../constants';
|
|
8
|
-
import { CustomFieldDefinition, CustomFieldValue } from '../../models';
|
|
9
6
|
|
|
10
7
|
/**
|
|
11
8
|
* Builds a WHERE clause and replacements for free-text search by custom fields.
|
|
@@ -20,12 +17,13 @@ import { CustomFieldDefinition, CustomFieldValue } from '../../models';
|
|
|
20
17
|
* @param {CustomFieldDefinitionType[]} excludedCustomFieldsTypes - An array of custom field types
|
|
21
18
|
* to exclude from the search
|
|
22
19
|
*
|
|
23
|
-
* @returns {CustomFieldsSearchPayload} - An object containing the
|
|
20
|
+
* @returns {CustomFieldsSearchPayload} - An object containing the WHERE clause and replacements
|
|
21
|
+
* for Sequelize.
|
|
24
22
|
*/
|
|
25
23
|
|
|
26
24
|
interface CustomFieldsSearchPayload {
|
|
27
25
|
where: WhereOptions;
|
|
28
|
-
|
|
26
|
+
replacements: BindOrReplacements;
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
export const generateRandomString = (length = 5): string => {
|
|
@@ -41,33 +39,28 @@ export const generateCustomFieldSearchQueryPayload = (
|
|
|
41
39
|
CustomFieldDefinitionType.DATETIME,
|
|
42
40
|
CustomFieldDefinitionType.DATE,
|
|
43
41
|
],
|
|
44
|
-
): CustomFieldsSearchPayload =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
on: {
|
|
68
|
-
value: Sequelize.where(Sequelize.cast(Sequelize.col('value'), 'text'), { [Op.iLike]: `%${searchTerm}%` }),
|
|
69
|
-
model_id: Sequelize.where(Sequelize.col('model_id'), { [Op.eq]: Sequelize.col(`${model.name}.id`) }),
|
|
42
|
+
): CustomFieldsSearchPayload => {
|
|
43
|
+
const excludedTypesString = customFieldsTypesToExclude.map((type) => `'${type}'`).join(',');
|
|
44
|
+
|
|
45
|
+
const subQuery = 'EXISTS ('
|
|
46
|
+
+ ' SELECT 1'
|
|
47
|
+
+ ' FROM "custom_field_values" AS "cv"'
|
|
48
|
+
+ ' INNER JOIN custom_field_definitions AS cd '
|
|
49
|
+
+ ` ON cd.entity_id = '${entityId}'`
|
|
50
|
+
+ ' AND cv.custom_field_definition_id = cd.id'
|
|
51
|
+
+ ` AND cd.model_type = '${model.name}'`
|
|
52
|
+
+ ` ${excludedTypesString ? `AND cd.field_type NOT IN (${excludedTypesString})` : ''}`
|
|
53
|
+
+ ' WHERE'
|
|
54
|
+
+ ' "cv"."deleted_at" IS NULL'
|
|
55
|
+
+ ` AND "cv"."model_id" = "${model.name}"."id"`
|
|
56
|
+
+ ' AND CAST("cv"."value" AS TEXT) ILIKE :searchTerm)';
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
where: {
|
|
60
|
+
[Op.or]: [
|
|
61
|
+
Sequelize.where(Sequelize.literal(subQuery), true),
|
|
62
|
+
],
|
|
70
63
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
64
|
+
replacements: { searchTerm: `%${searchTerm}%` },
|
|
65
|
+
};
|
|
66
|
+
};
|
package/src/utils/init.ts
CHANGED
|
@@ -84,7 +84,8 @@ export const removeHooks = (models: Models[], getModel: ModelFetcher): void => {
|
|
|
84
84
|
/**
|
|
85
85
|
* Necessary associations for the {@link customFieldsFilterScope} scope
|
|
86
86
|
*/
|
|
87
|
-
const addAssociations = (model: ModelCtor, modelName: string): void => {
|
|
87
|
+
const addAssociations = (model: ModelCtor, modelName: string, options: Pick<CustomFieldOptions, 'useCustomFieldsEntries'>): void => {
|
|
88
|
+
if (options?.useCustomFieldsEntries) return;
|
|
88
89
|
model.hasMany(CustomFieldValue, { foreignKey: 'modelId', as: 'customFieldValue' });
|
|
89
90
|
// TBC: maybe can be removed
|
|
90
91
|
CustomFieldValue.belongsTo(model, { foreignKey: 'modelId', as: modelName });
|
|
@@ -102,7 +103,7 @@ export const addScopes = (models: Models[], getModel: ModelFetcher, options: Pic
|
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
104
105
|
// Necessary associations for the filtering scope
|
|
105
|
-
addAssociations(model, name);
|
|
106
|
+
addAssociations(model, name, options);
|
|
106
107
|
// Add filter scope
|
|
107
108
|
model.addScope(CUSTOM_FIELDS_FILTER_SCOPE, customFieldsFilterScope(name, options));
|
|
108
109
|
model.addScope(CUSTOM_FIELDS_SORT_SCOPE, customFieldsSortScope(name, options));
|