@autofleet/sadot 0.7.0-beta.2.1 → 0.7.0-beta.2.3

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.
@@ -24,14 +24,14 @@ export type CustomFieldFilterOptions = {
24
24
  * @param name - The model type name used to join custom_field_definitions.
25
25
  * @returns A function that takes conditions and returns the Sequelize options object.
26
26
  */
27
- export declare const customFieldsFilterScope: (name: string) => ({ replacementsMap: replacements, scopeValue: conditions, }: {
28
- replacementsMap: Record<string, string>;
29
- scopeValue: Record<string, ConditionValue>;
27
+ export declare const customFieldsFilterScope: (name: string) => ({ replacementsMap, scopeValue }: {
28
+ replacementsMap: any;
29
+ scopeValue: any;
30
30
  }) => CustomFieldFilterOptions;
31
31
  export declare const scopeName = "filterByCustomFields";
32
32
  export declare const customFieldsSortScope: (name: string) => ({ replacementsMap, scopeValue: sort }: {
33
- replacementsMap: Record<string, string>;
34
- scopeValue: string[];
33
+ replacementsMap: any;
34
+ scopeValue: any;
35
35
  }) => {
36
36
  attributes?: undefined;
37
37
  order?: undefined;
@@ -41,6 +41,6 @@ export declare const customFieldsSortScope: (name: string) => ({ replacementsMap
41
41
  include: (string | import("sequelize/types/utils").Literal)[][];
42
42
  };
43
43
  order: import("sequelize/types/utils").Literal[];
44
- replacements: Record<string, string>;
44
+ replacements: any;
45
45
  };
46
46
  export {};
@@ -21,42 +21,6 @@ const castIfNeeded = (conditionValue) => {
21
21
  return '';
22
22
  };
23
23
  const AND_DELIMETER = ' AND ';
24
- const OR_DELIMETER = ' OR ';
25
- const CD_TABLE_ALIAS = 'cd';
26
- const CD_NAME_COLUMN = `${CD_TABLE_ALIAS}.name`;
27
- const CV_TABLE_ALIAS = 'cv';
28
- const CV_VALUE_COLUMN = `(${CV_TABLE_ALIAS}.value)`;
29
- const castValueToJsonb = (value) => `to_jsonb(${value}::text)`;
30
- /**
31
- * Helper function to build condition strings for the WHERE clause.
32
- */
33
- // eslint-disable-next-line max-len
34
- const buildConditionString = (key, condition, replacements) => {
35
- const replacementKey = Object.keys(replacements).find((randomString) => replacements[randomString] === key);
36
- if (!replacementKey)
37
- return false;
38
- if (Array.isArray(condition)) {
39
- if (condition.length === 0)
40
- return false;
41
- if (typeof condition[0] === 'string') {
42
- const values = condition.map((v) => `:${replacements[v]}`).join(',');
43
- return `(custom_fields->> :${replacementKey}) IN (${values})`;
44
- }
45
- return condition.map((c) => {
46
- const valRep = replacements[c.value];
47
- return `(custom_fields->> :${replacementKey})${castIfNeeded(c.value)} ${c.operator} :${valRep}`;
48
- }).join(AND_DELIMETER);
49
- }
50
- if (typeof condition === 'string' || typeof condition === 'number') {
51
- const conditionRep = replacements[condition];
52
- return `(custom_fields->> :${replacementKey}) ${castIfNeeded(condition)} = :${conditionRep}`;
53
- }
54
- if (condition?.operator) {
55
- const valueRep = replacements[condition.value];
56
- return `(custom_fields->> :${replacementKey}) ${castIfNeeded(condition.value)} ${condition.operator} :${valueRep}`;
57
- }
58
- return false;
59
- };
60
24
  /**
61
25
  * A Sequelize scope for filtering models by custom fields.
62
26
  * This scope builds a WHERE clause to be applied on the main query.
@@ -64,16 +28,49 @@ const buildConditionString = (key, condition, replacements) => {
64
28
  * @param name - The model type name used to join custom_field_definitions.
65
29
  * @returns A function that takes conditions and returns the Sequelize options object.
66
30
  */
67
- const customFieldsFilterScope = (name) => ({ replacementsMap: replacements, scopeValue: conditions, }) => {
31
+ const customFieldsFilterScope = (name) => ({ replacementsMap, scopeValue }) => {
32
+ const conditions = scopeValue;
33
+ const replacements = replacementsMap;
68
34
  if (!conditions || Object.keys(conditions).length === 0) {
69
35
  return {};
70
36
  }
71
37
  // Build the WHERE clause for custom field filtering
72
38
  const conditionsStrings = Object.entries(conditions)
73
- .map(([key, condition]) => buildConditionString(key, condition, replacements))
39
+ .map(([key, condition]) => {
40
+ const replacemetKey = Object.keys(replacements).find((randomString) => replacements[randomString] === key);
41
+ if (!replacemetKey)
42
+ return false;
43
+ if (Array.isArray(condition)) {
44
+ if (condition.length === 0) {
45
+ // if empty array, the condition is ignored
46
+ return false;
47
+ }
48
+ if (typeof condition[0] === 'string') {
49
+ const values = condition.map((v) => {
50
+ const valRandom = Object.keys(replacements).find((randomString) => replacements[randomString] === v);
51
+ return ` :${valRandom} `;
52
+ }).join(',');
53
+ return `(custom_fields->> :${replacemetKey} ) IN ( ${values} )`;
54
+ }
55
+ return condition
56
+ .map((c) => {
57
+ const valRep = Object.keys(replacements).find((key) => replacements[key] === c.value);
58
+ return `(custom_fields->> :${replacemetKey} )${castIfNeeded(c.value)} ${c.operator} :${valRep}`;
59
+ }).join(AND_DELIMETER);
60
+ }
61
+ if (typeof condition === 'string' || typeof condition === 'number') {
62
+ const conditionRep = Object.keys(replacements).find((key) => replacements[key] === condition);
63
+ return `(custom_fields->> :${replacemetKey} ) ${castIfNeeded(condition)} = :${conditionRep}`;
64
+ }
65
+ if (condition?.operator) {
66
+ const valueRep = Object.keys(replacements).find((key) => replacements[key] === condition.value);
67
+ return `(custom_fields->> :${replacemetKey} ) ${castIfNeeded(condition.value)} ${condition.operator} :${valueRep}`;
68
+ }
69
+ return false;
70
+ })
74
71
  .filter(Boolean);
75
72
  if (conditionsStrings.length === 0) {
76
- return { replacements };
73
+ return {};
77
74
  }
78
75
  const customFieldConditions = conditionsStrings.join(AND_DELIMETER);
79
76
  const subQuery = `${'SELECT model_id FROM ('
@@ -100,21 +97,20 @@ const customFieldsSortScope = (name) => ({ replacementsMap, scopeValue: sort })
100
97
  }
101
98
  const randomStr = (0, helpers_1.generateRandomString)();
102
99
  const includes = Object.entries(sort).map(([key]) => {
103
- const replacementKey = Object.keys(replacementsMap)
104
- .find((randomString) => replacementsMap[randomString] === key);
105
- return [
100
+ const replacemetKey = Object.keys(replacementsMap).find((randomString) => replacementsMap[randomString] === key);
101
+ return ([
106
102
  sequelize_typescript_1.Sequelize.literal(`(
107
- SELECT value
108
- FROM (
109
- SELECT cv.model_id, cv.value
110
- FROM custom_field_values AS cv
111
- INNER JOIN custom_field_definitions AS cd ON cv.custom_field_definition_id = cd.id
112
- AND cd.model_type = '${name}'
113
- WHERE cv.model_id = "${name}"."id" AND cd.name = :${replacementKey}
114
- ) AS CustomFieldAggregation
115
- )`),
116
- randomStr,
117
- ];
103
+ SELECT value
104
+ FROM (SELECT cv.model_id, cv.value
105
+ FROM custom_field_values AS cv INNER JOIN custom_field_definitions AS cd
106
+ ON cv.custom_field_definition_id = cd.id
107
+ AND cd.model_type = '${name}'
108
+ WHERE cv.model_id = "${name}"."id"
109
+ AND cd.name = :${replacemetKey}
110
+ ) AS CustomFieldAggregation
111
+ )
112
+ `), randomStr,
113
+ ]);
118
114
  });
119
115
  const orders = Object.entries(sort).map(([, value]) => sequelize_typescript_1.Sequelize.literal(`"${randomStr}" ${value}`));
120
116
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/sadot",
3
- "version": "0.7.0-beta.2.1",
3
+ "version": "0.7.0-beta.2.3",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  "linter": "./node_modules/.bin/eslint .",
10
10
  "test": "jest --forceExit --runInBand",
11
11
  "coverage": "jest --coverage --forceExit --runInBand && rm -rf ./coverage",
12
- "build-to-local-repo": "npm run build && cp -r dist/* ../$REPO/node_modules/$npm_package_name/dist",
12
+ "build-to-local-repo": "npm run build && cp -r dist/* ../task-ms/node_modules/@autofleet/sadot/dist",
13
13
  "dev": "nodemon",
14
14
  "watch": "npm-watch build-to-local-repo",
15
15
  "publish-dev": "npm run build && npm publish --tag dev"
@@ -13,73 +13,30 @@ const { CUSTOM_FIELDS_FILTER_SCOPE } = customFields;
13
13
  * More types to be added (TBA).
14
14
  */
15
15
  type ConditionWithOperator = {
16
- operator: string;
17
- value: string;
16
+ operator: string;
17
+ value: string;
18
18
  };
19
19
  export type ConditionValue = ConditionWithOperator | ConditionWithOperator[] | string | string[];
20
20
 
21
21
  export type CustomFieldSort = {
22
- field: string;
23
- direction: 'ASC' | 'DESC';
22
+ field: string;
23
+ direction: 'ASC' | 'DESC';
24
24
  }
25
25
 
26
26
  export type CustomFieldFilterOptions = {
27
- where?: WhereOptions;
28
- replacements?: Record<string, string>;
27
+ where?: WhereOptions;
28
+ replacements?: Record<string, string>;
29
29
  }
30
30
 
31
31
  const castIfNeeded = (conditionValue: string): string => {
32
32
  if (moment.isDate(conditionValue)) {
33
33
  return '::timestamp';
34
- }
35
- if (!Number.isNaN(Number(conditionValue))) {
34
+ } if (!Number.isNaN(Number(conditionValue))) {
36
35
  return '::numeric';
37
36
  }
38
37
  return '';
39
38
  };
40
39
  const AND_DELIMETER = ' AND ';
41
- const OR_DELIMETER = ' OR ';
42
-
43
- const CD_TABLE_ALIAS = 'cd';
44
- const CD_NAME_COLUMN = `${CD_TABLE_ALIAS}.name`;
45
- const CV_TABLE_ALIAS = 'cv';
46
- const CV_VALUE_COLUMN = `(${CV_TABLE_ALIAS}.value)`;
47
- const castValueToJsonb = (value) => `to_jsonb(${value}::text)`;
48
-
49
- /**
50
- * Helper function to build condition strings for the WHERE clause.
51
- */
52
- // eslint-disable-next-line max-len
53
- const buildConditionString = (key: string, condition: ConditionValue | ConditionValue[], replacements: Record<string, string>): string | false => {
54
- const replacementKey = Object.keys(replacements).find((randomString) => replacements[randomString] === key);
55
- if (!replacementKey) return false;
56
-
57
- if (Array.isArray(condition)) {
58
- if (condition.length === 0) return false;
59
-
60
- if (typeof condition[0] === 'string') {
61
- const values = condition.map((v) => `:${replacements[v]}`).join(',');
62
- return `(custom_fields->> :${replacementKey}) IN (${values})`;
63
- }
64
-
65
- return condition.map((c) => {
66
- const valRep = replacements[c.value];
67
- return `(custom_fields->> :${replacementKey})${castIfNeeded(c.value)} ${c.operator} :${valRep}`;
68
- }).join(AND_DELIMETER);
69
- }
70
-
71
- if (typeof condition === 'string'|| typeof condition === 'number') {
72
- const conditionRep = replacements[condition];
73
- return `(custom_fields->> :${replacementKey}) ${castIfNeeded(condition)} = :${conditionRep}`;
74
- }
75
-
76
- if (condition?.operator) {
77
- const valueRep = replacements[condition.value];
78
- return `(custom_fields->> :${replacementKey}) ${castIfNeeded(condition.value)} ${condition.operator} :${valueRep}`;
79
- }
80
-
81
- return false;
82
- };
83
40
 
84
41
  /**
85
42
  * A Sequelize scope for filtering models by custom fields.
@@ -90,31 +47,60 @@ const buildConditionString = (key: string, condition: ConditionValue | Condition
90
47
  */
91
48
  export const customFieldsFilterScope = (
92
49
  name: string,
93
- ) => (
94
- {
95
- replacementsMap: replacements,
96
- scopeValue: conditions,
97
- }: { replacementsMap: Record<string, string>, scopeValue: Record<string, ConditionValue> },
98
- ): CustomFieldFilterOptions => {
50
+ ) => ({ replacementsMap, scopeValue }): CustomFieldFilterOptions => {
51
+ const conditions: Record<string, ConditionValue> = scopeValue;
52
+ const replacements: Record<string, string> = replacementsMap;
99
53
  if (!conditions || Object.keys(conditions).length === 0) {
100
54
  return {};
101
55
  }
102
-
103
56
  // Build the WHERE clause for custom field filtering
104
57
  const conditionsStrings = Object.entries(conditions)
105
- .map(([key, condition]) => buildConditionString(key, condition, replacements))
106
- .filter(Boolean) as string[];
58
+ .map(
59
+ ([key, condition]) => {
60
+ const replacemetKey = Object.keys(replacements).find((randomString) => replacements[randomString] === key);
61
+ if (!replacemetKey) return false;
62
+
63
+ if (Array.isArray(condition)) {
64
+ if (condition.length === 0) {
65
+ // if empty array, the condition is ignored
66
+ return false;
67
+ }
68
+ if (typeof condition[0] === 'string') {
69
+ const values = condition.map((v) => {
70
+ const valRandom = Object.keys(replacements).find((randomString) => replacements[randomString] === v);
71
+ return ` :${valRandom} `;
72
+ }).join(',');
73
+ return `(custom_fields->> :${replacemetKey} ) IN ( ${values} )`;
74
+ }
75
+ return condition
76
+ .map((c) => {
77
+ const valRep = Object.keys(replacements).find((key) => replacements[key] === c.value);
78
+ return `(custom_fields->> :${replacemetKey} )${castIfNeeded(c.value)} ${c.operator} :${valRep}`;
79
+ }).join(AND_DELIMETER);
80
+ }
81
+ if (typeof condition === 'string' || typeof condition === 'number') {
82
+ const conditionRep = Object.keys(replacements).find((key) => replacements[key] === condition);
83
+ return `(custom_fields->> :${replacemetKey} ) ${castIfNeeded(condition)} = :${conditionRep}`;
84
+ }
85
+ if (condition?.operator) {
86
+ const valueRep = Object.keys(replacements).find((key) => replacements[key] === condition.value);
87
+ return `(custom_fields->> :${replacemetKey} ) ${castIfNeeded(condition.value)} ${condition.operator} :${valueRep}`;
88
+ }
89
+ return false;
90
+ },
91
+ )
92
+ .filter(Boolean);
107
93
  if (conditionsStrings.length === 0) {
108
- return { replacements };
94
+ return {};
109
95
  }
110
96
  const customFieldConditions = conditionsStrings.join(AND_DELIMETER);
111
97
  const subQuery = `${'SELECT model_id FROM ('
112
- + 'SELECT cv.model_id, jsonb_object_agg(cd.name, cv.value) AS custom_fields '
113
- + 'FROM custom_field_values AS cv '
114
- + 'INNER JOIN custom_field_definitions AS cd ON cv.custom_field_definition_id = cd.id '
115
- + `AND cd.model_type = '${name}'`
116
- + 'GROUP BY cv.model_id'
117
- + ') AS CustomFieldAggregation WHERE '} ${customFieldConditions}`;
98
+ + 'SELECT cv.model_id, jsonb_object_agg(cd.name, cv.value) AS custom_fields '
99
+ + 'FROM custom_field_values AS cv '
100
+ + 'INNER JOIN custom_field_definitions AS cd ON cv.custom_field_definition_id = cd.id '
101
+ + `AND cd.model_type = '${name}'`
102
+ + 'GROUP BY cv.model_id'
103
+ + ') AS CustomFieldAggregation WHERE '} ${customFieldConditions}`;
118
104
  return {
119
105
  where: {
120
106
  id: {
@@ -129,28 +115,26 @@ export const scopeName = CUSTOM_FIELDS_FILTER_SCOPE;
129
115
 
130
116
  export const customFieldsSortScope = (
131
117
  name: string,
132
- ) => ({ replacementsMap, scopeValue: sort }: { replacementsMap: Record<string, string>, scopeValue: string[] }) => {
118
+ ) => ({ replacementsMap, scopeValue: sort }) => {
133
119
  if (!sort || sort.length === 0) {
134
120
  return {};
135
121
  }
136
-
137
122
  const randomStr = generateRandomString();
138
123
  const includes = Object.entries(sort).map(([key]) => {
139
- const replacementKey = Object.keys(replacementsMap)
140
- .find((randomString) => replacementsMap[randomString] === key);
141
- return [
124
+ const replacemetKey = Object.keys(replacementsMap).find((randomString) => replacementsMap[randomString] === key);
125
+ return ([
142
126
  Sequelize.literal(`(
143
- SELECT value
144
- FROM (
145
- SELECT cv.model_id, cv.value
146
- FROM custom_field_values AS cv
147
- INNER JOIN custom_field_definitions AS cd ON cv.custom_field_definition_id = cd.id
148
- AND cd.model_type = '${name}'
149
- WHERE cv.model_id = "${name}"."id" AND cd.name = :${replacementKey}
150
- ) AS CustomFieldAggregation
151
- )`),
152
- randomStr,
153
- ];
127
+ SELECT value
128
+ FROM (SELECT cv.model_id, cv.value
129
+ FROM custom_field_values AS cv INNER JOIN custom_field_definitions AS cd
130
+ ON cv.custom_field_definition_id = cd.id
131
+ AND cd.model_type = '${name}'
132
+ WHERE cv.model_id = "${name}"."id"
133
+ AND cd.name = :${replacemetKey}
134
+ ) AS CustomFieldAggregation
135
+ )
136
+ `), randomStr,
137
+ ]);
154
138
  });
155
139
 
156
140
  const orders = Object.entries(sort).map(([, value]) => Sequelize.literal(`"${randomStr}" ${value}`));