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

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,51 @@ 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') {
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 {
74
+ replacements,
75
+ };
77
76
  }
78
77
  const customFieldConditions = conditionsStrings.join(AND_DELIMETER);
79
78
  const subQuery = `${'SELECT model_id FROM ('
@@ -100,21 +99,21 @@ const customFieldsSortScope = (name) => ({ replacementsMap, scopeValue: sort })
100
99
  }
101
100
  const randomStr = (0, helpers_1.generateRandomString)();
102
101
  const includes = Object.entries(sort).map(([key]) => {
103
- const replacementKey = Object.keys(replacementsMap)
104
- .find((randomString) => replacementsMap[randomString] === key);
105
- return [
102
+ const replacemetKey = Object.keys(replacementsMap).find((randomString) => replacementsMap[randomString] === key);
103
+ console.log('sort replacemetKey:', replacemetKey);
104
+ return ([
106
105
  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
- ];
106
+ SELECT value
107
+ FROM (SELECT cv.model_id, cv.value
108
+ FROM custom_field_values AS cv INNER JOIN custom_field_definitions AS cd
109
+ ON cv.custom_field_definition_id = cd.id
110
+ AND cd.model_type = '${name}'
111
+ WHERE cv.model_id = "${name}"."id"
112
+ AND cd.name = :${replacemetKey}
113
+ ) AS CustomFieldAggregation
114
+ )
115
+ `), randomStr,
116
+ ]);
118
117
  });
119
118
  const orders = Object.entries(sort).map(([, value]) => sequelize_typescript_1.Sequelize.literal(`"${randomStr}" ${value}`));
120
119
  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.2",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -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,62 @@ 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') {
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 {
95
+ replacements,
96
+ };
109
97
  }
110
98
  const customFieldConditions = conditionsStrings.join(AND_DELIMETER);
111
99
  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}`;
100
+ + 'SELECT cv.model_id, jsonb_object_agg(cd.name, cv.value) AS custom_fields '
101
+ + 'FROM custom_field_values AS cv '
102
+ + 'INNER JOIN custom_field_definitions AS cd ON cv.custom_field_definition_id = cd.id '
103
+ + `AND cd.model_type = '${name}'`
104
+ + 'GROUP BY cv.model_id'
105
+ + ') AS CustomFieldAggregation WHERE '} ${customFieldConditions}`;
118
106
  return {
119
107
  where: {
120
108
  id: {
@@ -129,28 +117,27 @@ export const scopeName = CUSTOM_FIELDS_FILTER_SCOPE;
129
117
 
130
118
  export const customFieldsSortScope = (
131
119
  name: string,
132
- ) => ({ replacementsMap, scopeValue: sort }: { replacementsMap: Record<string, string>, scopeValue: string[] }) => {
120
+ ) => ({ replacementsMap, scopeValue: sort }) => {
133
121
  if (!sort || sort.length === 0) {
134
122
  return {};
135
123
  }
136
-
137
124
  const randomStr = generateRandomString();
138
125
  const includes = Object.entries(sort).map(([key]) => {
139
- const replacementKey = Object.keys(replacementsMap)
140
- .find((randomString) => replacementsMap[randomString] === key);
141
- return [
126
+ const replacemetKey = Object.keys(replacementsMap).find((randomString) => replacementsMap[randomString] === key);
127
+ console.log('sort replacemetKey:', replacemetKey);
128
+ return ([
142
129
  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
- ];
130
+ SELECT value
131
+ FROM (SELECT cv.model_id, cv.value
132
+ FROM custom_field_values AS cv INNER JOIN custom_field_definitions AS cd
133
+ ON cv.custom_field_definition_id = cd.id
134
+ AND cd.model_type = '${name}'
135
+ WHERE cv.model_id = "${name}"."id"
136
+ AND cd.name = :${replacemetKey}
137
+ ) AS CustomFieldAggregation
138
+ )
139
+ `), randomStr,
140
+ ]);
154
141
  });
155
142
 
156
143
  const orders = Object.entries(sort).map(([, value]) => Sequelize.literal(`"${randomStr}" ${value}`));