@beabee/beabee-common 1.6.1 → 1.7.1
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/cjs/search/index.js +43 -10
- package/dist/esm/search/index.js +43 -10
- package/dist/types/search/index.d.ts +134 -12
- package/package.json +1 -1
package/dist/cjs/search/index.js
CHANGED
|
@@ -34,8 +34,10 @@ exports.ruleOperators = [
|
|
|
34
34
|
"is_empty",
|
|
35
35
|
"is_not_empty",
|
|
36
36
|
];
|
|
37
|
-
const
|
|
38
|
-
|
|
37
|
+
const equalityOperators = {
|
|
38
|
+
equal: { args: 1 },
|
|
39
|
+
not_equal: { args: 1 },
|
|
40
|
+
};
|
|
39
41
|
const numericOperators = {
|
|
40
42
|
...equalityOperators,
|
|
41
43
|
between: { args: 2 },
|
|
@@ -49,6 +51,7 @@ const arrayOperators = {
|
|
|
49
51
|
contains: { args: 1 },
|
|
50
52
|
not_contains: { args: 1 },
|
|
51
53
|
};
|
|
54
|
+
// Special operator can be applied across all fields if they are nullable
|
|
52
55
|
exports.nullableOperators = {
|
|
53
56
|
is_empty: { args: 0 },
|
|
54
57
|
is_not_empty: { args: 0 },
|
|
@@ -64,11 +67,13 @@ exports.operatorsByType = {
|
|
|
64
67
|
},
|
|
65
68
|
date: numericOperators,
|
|
66
69
|
number: numericOperators,
|
|
67
|
-
boolean: { equal },
|
|
70
|
+
boolean: { equal: equalityOperators.equal },
|
|
68
71
|
array: arrayOperators,
|
|
69
72
|
enum: equalityOperators,
|
|
70
73
|
contact: equalityOperators,
|
|
71
74
|
};
|
|
75
|
+
// More general type to allow mapping while maintaining full type above
|
|
76
|
+
const operatorsByTypeMap = exports.operatorsByType;
|
|
72
77
|
// *** Helper methods ***
|
|
73
78
|
function isRuleGroup(ruleOrGroup) {
|
|
74
79
|
return "condition" in ruleOrGroup;
|
|
@@ -79,17 +84,44 @@ function validateRule(filters, rule) {
|
|
|
79
84
|
if (!filter) {
|
|
80
85
|
return false; // Invalid field
|
|
81
86
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
if (rule.operator in exports.nullableOperators) {
|
|
88
|
+
if (!filter.nullable && filter.type !== "text") {
|
|
89
|
+
return false; // Field cannot be empty (text can always be empty)
|
|
90
|
+
}
|
|
91
|
+
if (rule.value.length !== 0) {
|
|
92
|
+
return false; // Should have no args
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
const operator = operatorsByTypeMap[filter.type][rule.operator];
|
|
97
|
+
if (!operator) {
|
|
98
|
+
return false; // Invalid operator
|
|
99
|
+
}
|
|
100
|
+
if (operator.args !== rule.value.length) {
|
|
101
|
+
return false; // Invalid number of args
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const expectedType = filter.type === "boolean" || filter.type === "number"
|
|
105
|
+
? filter.type
|
|
106
|
+
: "string";
|
|
107
|
+
if (rule.value.some((v) => typeof v !== expectedType)) {
|
|
108
|
+
return false; // Invalid value type
|
|
85
109
|
}
|
|
86
|
-
if (
|
|
87
|
-
|
|
110
|
+
if (filter.type === "date" &&
|
|
111
|
+
rule.value.some((v) => isNaN(+new Date(v)))) {
|
|
112
|
+
return false; // Invalid date
|
|
88
113
|
}
|
|
89
|
-
return
|
|
114
|
+
return {
|
|
115
|
+
...rule,
|
|
116
|
+
type: filter.type,
|
|
117
|
+
};
|
|
90
118
|
}
|
|
91
119
|
exports.validateRule = validateRule;
|
|
92
120
|
function validateRuleGroup(filters, ruleGroup) {
|
|
121
|
+
const validatedRuleGroup = {
|
|
122
|
+
condition: ruleGroup.condition,
|
|
123
|
+
rules: [],
|
|
124
|
+
};
|
|
93
125
|
for (const rule of ruleGroup.rules) {
|
|
94
126
|
const valid = isRuleGroup(rule)
|
|
95
127
|
? validateRuleGroup(filters, rule)
|
|
@@ -97,8 +129,9 @@ function validateRuleGroup(filters, ruleGroup) {
|
|
|
97
129
|
if (!valid) {
|
|
98
130
|
return false;
|
|
99
131
|
}
|
|
132
|
+
validatedRuleGroup.rules.push(valid);
|
|
100
133
|
}
|
|
101
|
-
return
|
|
134
|
+
return validatedRuleGroup;
|
|
102
135
|
}
|
|
103
136
|
exports.validateRuleGroup = validateRuleGroup;
|
|
104
137
|
function convertRuleGroupToFilters(ruleGroup) {
|
package/dist/esm/search/index.js
CHANGED
|
@@ -17,8 +17,10 @@ export const ruleOperators = [
|
|
|
17
17
|
"is_empty",
|
|
18
18
|
"is_not_empty",
|
|
19
19
|
];
|
|
20
|
-
const
|
|
21
|
-
|
|
20
|
+
const equalityOperators = {
|
|
21
|
+
equal: { args: 1 },
|
|
22
|
+
not_equal: { args: 1 },
|
|
23
|
+
};
|
|
22
24
|
const numericOperators = {
|
|
23
25
|
...equalityOperators,
|
|
24
26
|
between: { args: 2 },
|
|
@@ -32,6 +34,7 @@ const arrayOperators = {
|
|
|
32
34
|
contains: { args: 1 },
|
|
33
35
|
not_contains: { args: 1 },
|
|
34
36
|
};
|
|
37
|
+
// Special operator can be applied across all fields if they are nullable
|
|
35
38
|
export const nullableOperators = {
|
|
36
39
|
is_empty: { args: 0 },
|
|
37
40
|
is_not_empty: { args: 0 },
|
|
@@ -47,11 +50,13 @@ export const operatorsByType = {
|
|
|
47
50
|
},
|
|
48
51
|
date: numericOperators,
|
|
49
52
|
number: numericOperators,
|
|
50
|
-
boolean: { equal },
|
|
53
|
+
boolean: { equal: equalityOperators.equal },
|
|
51
54
|
array: arrayOperators,
|
|
52
55
|
enum: equalityOperators,
|
|
53
56
|
contact: equalityOperators,
|
|
54
57
|
};
|
|
58
|
+
// More general type to allow mapping while maintaining full type above
|
|
59
|
+
const operatorsByTypeMap = operatorsByType;
|
|
55
60
|
// *** Helper methods ***
|
|
56
61
|
export function isRuleGroup(ruleOrGroup) {
|
|
57
62
|
return "condition" in ruleOrGroup;
|
|
@@ -61,16 +66,43 @@ export function validateRule(filters, rule) {
|
|
|
61
66
|
if (!filter) {
|
|
62
67
|
return false; // Invalid field
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
if (rule.operator in nullableOperators) {
|
|
70
|
+
if (!filter.nullable && filter.type !== "text") {
|
|
71
|
+
return false; // Field cannot be empty (text can always be empty)
|
|
72
|
+
}
|
|
73
|
+
if (rule.value.length !== 0) {
|
|
74
|
+
return false; // Should have no args
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const operator = operatorsByTypeMap[filter.type][rule.operator];
|
|
79
|
+
if (!operator) {
|
|
80
|
+
return false; // Invalid operator
|
|
81
|
+
}
|
|
82
|
+
if (operator.args !== rule.value.length) {
|
|
83
|
+
return false; // Invalid number of args
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const expectedType = filter.type === "boolean" || filter.type === "number"
|
|
87
|
+
? filter.type
|
|
88
|
+
: "string";
|
|
89
|
+
if (rule.value.some((v) => typeof v !== expectedType)) {
|
|
90
|
+
return false; // Invalid value type
|
|
67
91
|
}
|
|
68
|
-
if (
|
|
69
|
-
|
|
92
|
+
if (filter.type === "date" &&
|
|
93
|
+
rule.value.some((v) => isNaN(+new Date(v)))) {
|
|
94
|
+
return false; // Invalid date
|
|
70
95
|
}
|
|
71
|
-
return
|
|
96
|
+
return {
|
|
97
|
+
...rule,
|
|
98
|
+
type: filter.type,
|
|
99
|
+
};
|
|
72
100
|
}
|
|
73
101
|
export function validateRuleGroup(filters, ruleGroup) {
|
|
102
|
+
const validatedRuleGroup = {
|
|
103
|
+
condition: ruleGroup.condition,
|
|
104
|
+
rules: [],
|
|
105
|
+
};
|
|
74
106
|
for (const rule of ruleGroup.rules) {
|
|
75
107
|
const valid = isRuleGroup(rule)
|
|
76
108
|
? validateRuleGroup(filters, rule)
|
|
@@ -78,8 +110,9 @@ export function validateRuleGroup(filters, ruleGroup) {
|
|
|
78
110
|
if (!valid) {
|
|
79
111
|
return false;
|
|
80
112
|
}
|
|
113
|
+
validatedRuleGroup.rules.push(valid);
|
|
81
114
|
}
|
|
82
|
-
return
|
|
115
|
+
return validatedRuleGroup;
|
|
83
116
|
}
|
|
84
117
|
export function convertRuleGroupToFilters(ruleGroup) {
|
|
85
118
|
if (!ruleGroup) {
|
|
@@ -1,14 +1,28 @@
|
|
|
1
1
|
export declare const ruleOperators: readonly ["equal", "not_equal", "less", "less_or_equal", "greater", "greater_or_equal", "between", "not_between", "begins_with", "not_begins_with", "contains", "not_contains", "ends_with", "not_ends_with", "is_empty", "is_not_empty"];
|
|
2
2
|
export declare type RuleOperator = typeof ruleOperators[number];
|
|
3
3
|
export declare type RuleValue = string | number | boolean;
|
|
4
|
-
export interface Rule
|
|
5
|
-
field:
|
|
4
|
+
export interface Rule {
|
|
5
|
+
field: string;
|
|
6
6
|
operator: RuleOperator;
|
|
7
7
|
value: RuleValue[];
|
|
8
8
|
}
|
|
9
|
-
export interface RuleGroup
|
|
9
|
+
export interface RuleGroup {
|
|
10
10
|
condition: "AND" | "OR";
|
|
11
|
-
rules: (RuleGroup
|
|
11
|
+
rules: (RuleGroup | Rule)[];
|
|
12
|
+
}
|
|
13
|
+
interface BaseValidatedRule<T extends FilterType, F extends string, V> {
|
|
14
|
+
type: T;
|
|
15
|
+
field: F;
|
|
16
|
+
operator: keyof typeof operatorsByType[T];
|
|
17
|
+
value: V[];
|
|
18
|
+
}
|
|
19
|
+
declare type ValidatedNumberRule<Field extends string> = BaseValidatedRule<"number", Field, number>;
|
|
20
|
+
declare type ValidatedStringRule<Field extends string> = BaseValidatedRule<Exclude<FilterType, "number" | "boolean">, Field, string>;
|
|
21
|
+
declare type ValidatedBooleanRule<Field extends string> = BaseValidatedRule<"boolean", Field, boolean>;
|
|
22
|
+
export declare type ValidatedRule<Field extends string> = ValidatedNumberRule<Field> | ValidatedStringRule<Field> | ValidatedBooleanRule<Field>;
|
|
23
|
+
export interface ValidatedRuleGroup<Field extends string> {
|
|
24
|
+
condition: "AND" | "OR";
|
|
25
|
+
rules: (ValidatedRuleGroup<Field> | ValidatedRule<Field>)[];
|
|
12
26
|
}
|
|
13
27
|
export declare type FilterType = "text" | "date" | "number" | "boolean" | "array" | "enum" | "contact";
|
|
14
28
|
export declare type FilterValue = RuleValue;
|
|
@@ -24,7 +38,115 @@ export declare const nullableOperators: {
|
|
|
24
38
|
args: number;
|
|
25
39
|
};
|
|
26
40
|
};
|
|
27
|
-
export declare const operatorsByType:
|
|
41
|
+
export declare const operatorsByType: {
|
|
42
|
+
readonly text: {
|
|
43
|
+
readonly begins_with: {
|
|
44
|
+
readonly args: 1;
|
|
45
|
+
};
|
|
46
|
+
readonly ends_with: {
|
|
47
|
+
readonly args: 1;
|
|
48
|
+
};
|
|
49
|
+
readonly not_begins_with: {
|
|
50
|
+
readonly args: 1;
|
|
51
|
+
};
|
|
52
|
+
readonly not_ends_with: {
|
|
53
|
+
readonly args: 1;
|
|
54
|
+
};
|
|
55
|
+
readonly contains: {
|
|
56
|
+
args: number;
|
|
57
|
+
};
|
|
58
|
+
readonly not_contains: {
|
|
59
|
+
args: number;
|
|
60
|
+
};
|
|
61
|
+
readonly equal: {
|
|
62
|
+
args: number;
|
|
63
|
+
};
|
|
64
|
+
readonly not_equal: {
|
|
65
|
+
args: number;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
readonly date: {
|
|
69
|
+
between: {
|
|
70
|
+
args: number;
|
|
71
|
+
};
|
|
72
|
+
not_between: {
|
|
73
|
+
args: number;
|
|
74
|
+
};
|
|
75
|
+
less: {
|
|
76
|
+
args: number;
|
|
77
|
+
};
|
|
78
|
+
greater: {
|
|
79
|
+
args: number;
|
|
80
|
+
};
|
|
81
|
+
less_or_equal: {
|
|
82
|
+
args: number;
|
|
83
|
+
};
|
|
84
|
+
greater_or_equal: {
|
|
85
|
+
args: number;
|
|
86
|
+
};
|
|
87
|
+
equal: {
|
|
88
|
+
args: number;
|
|
89
|
+
};
|
|
90
|
+
not_equal: {
|
|
91
|
+
args: number;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
readonly number: {
|
|
95
|
+
between: {
|
|
96
|
+
args: number;
|
|
97
|
+
};
|
|
98
|
+
not_between: {
|
|
99
|
+
args: number;
|
|
100
|
+
};
|
|
101
|
+
less: {
|
|
102
|
+
args: number;
|
|
103
|
+
};
|
|
104
|
+
greater: {
|
|
105
|
+
args: number;
|
|
106
|
+
};
|
|
107
|
+
less_or_equal: {
|
|
108
|
+
args: number;
|
|
109
|
+
};
|
|
110
|
+
greater_or_equal: {
|
|
111
|
+
args: number;
|
|
112
|
+
};
|
|
113
|
+
equal: {
|
|
114
|
+
args: number;
|
|
115
|
+
};
|
|
116
|
+
not_equal: {
|
|
117
|
+
args: number;
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
readonly boolean: {
|
|
121
|
+
readonly equal: {
|
|
122
|
+
args: number;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
readonly array: {
|
|
126
|
+
contains: {
|
|
127
|
+
args: number;
|
|
128
|
+
};
|
|
129
|
+
not_contains: {
|
|
130
|
+
args: number;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
readonly enum: {
|
|
134
|
+
equal: {
|
|
135
|
+
args: number;
|
|
136
|
+
};
|
|
137
|
+
not_equal: {
|
|
138
|
+
args: number;
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
readonly contact: {
|
|
142
|
+
equal: {
|
|
143
|
+
args: number;
|
|
144
|
+
};
|
|
145
|
+
not_equal: {
|
|
146
|
+
args: number;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
};
|
|
28
150
|
interface BaseFilterArgs {
|
|
29
151
|
type: FilterType;
|
|
30
152
|
nullable?: boolean;
|
|
@@ -49,18 +171,18 @@ export interface Paginated<T> {
|
|
|
49
171
|
count: number;
|
|
50
172
|
total: number;
|
|
51
173
|
}
|
|
52
|
-
export interface PaginatedQuery
|
|
174
|
+
export interface PaginatedQuery {
|
|
53
175
|
limit?: number;
|
|
54
176
|
offset?: number;
|
|
55
177
|
sort?: string;
|
|
56
178
|
order?: "ASC" | "DESC";
|
|
57
|
-
rules?: RuleGroup
|
|
179
|
+
rules?: RuleGroup;
|
|
58
180
|
}
|
|
59
|
-
export declare function isRuleGroup
|
|
60
|
-
export declare function validateRule<Field extends string>(filters: Filters<Field>, rule: Rule
|
|
61
|
-
export declare function validateRuleGroup<Field extends string>(filters: Filters<Field>, ruleGroup: RuleGroup
|
|
62
|
-
export declare function convertRuleGroupToFilters(ruleGroup?: RuleGroup
|
|
63
|
-
export declare function convertFiltersToRuleGroup(matchType: "all" | "any", filters: Filter[]): RuleGroup
|
|
181
|
+
export declare function isRuleGroup(ruleOrGroup: Rule | RuleGroup): ruleOrGroup is RuleGroup;
|
|
182
|
+
export declare function validateRule<Field extends string>(filters: Filters<Field>, rule: Rule): ValidatedRule<Field> | false;
|
|
183
|
+
export declare function validateRuleGroup<Field extends string>(filters: Filters<Field>, ruleGroup: RuleGroup): ValidatedRuleGroup<Field> | false;
|
|
184
|
+
export declare function convertRuleGroupToFilters(ruleGroup?: RuleGroup): Filter[] | null;
|
|
185
|
+
export declare function convertFiltersToRuleGroup(matchType: "all" | "any", filters: Filter[]): RuleGroup;
|
|
64
186
|
export * from "./callouts";
|
|
65
187
|
export * from "./contacts";
|
|
66
188
|
export * from "./notices";
|