-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfilter.ts
More file actions
118 lines (104 loc) · 3.46 KB
/
filter.ts
File metadata and controls
118 lines (104 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
type Match = Array<KeyValuePair>;
type Predicate = (field: string, value: any) => boolean;
const queryJson = (input: Array<any>, filters: Array<Predicate>): Array<Match> => {
const results: Array<Match> = [];
input.map((a: any) => {
const fields = getFields(a);
const potentialMatches = depthSearch(null, a, filters);
potentialMatches.map((pm: PotentialMatch) => {
let totalFound = 0;
filters.map((filter: Predicate): void => {
const found = pm.predicates.find((pmFilter): boolean => { return pmFilter === filter; });
if (found !== undefined) {
totalFound += 1;
}
});
if (totalFound === filters.length) {
results.push(pm.pairs);
}
});
});
return results;
};
interface KeyValuePair {
key: string;
value: any;
}
interface PotentialMatch {
pairs: Array<KeyValuePair>;
predicates: Array<Predicate>;
}
const depthSearch = (prefix: string | null, obj: any, filters: Array<Predicate>): Array<PotentialMatch> => {
let result: Array<PotentialMatch> = [];
const baseFields: Array<KeyValuePair> = [];
const basePredicates: Array<Predicate> = [];
if( obj == undefined || obj == null ){
return [];
}
Object.keys(obj).map((k: string ) => {
const v = obj[k];
const fullpath = (prefix === null) ? k : `${prefix}.${k}`;
if (typeof v !== "object") {
baseFields.push({
key: fullpath,
value: v,
});
filters.map((filter: Predicate) => {
if (filter(fullpath, v)) {
basePredicates.push(filter);
}
});
}
});
Object.keys(obj).map((k: string) => {
const v = obj[k];
const fullpath = (prefix === null) ? k : `${prefix}.${k}`;
if (typeof v === "object" && Array.isArray(v)) {
v.map((element: any) => {
const search = depthSearch(fullpath, element, filters);
result = result.concat(search);
});
}
else if (typeof v === "object") {
const search = depthSearch(fullpath, v, filters);
result = result.concat(search);
}
});
if (result.length > 0) { // If a child started meeting conditions, we want it.
result.map((pm: PotentialMatch) => {
pm.pairs = pm.pairs.concat(baseFields);
pm.predicates = pm.predicates.concat(basePredicates);
});
}
else if (basePredicates.length > 0) { // Otherwise base off ourself.
const pm: PotentialMatch = {
pairs: baseFields,
predicates: basePredicates,
};
result.push(pm);
}
return result;
};
const getFields = (source: any): Array<string> => {
const result: Array<string> = [];
const flat = (obj: any, stack: Array<string>): void => {
if( obj == undefined || obj == null ){
return [];
}
Object.keys(obj).forEach((k: string) => {
const s = stack.concat([k]);
const v = obj[k];
if (typeof v === 'object' && Array.isArray(v) ){
flat(v[0], s);
}
else if (typeof v === 'object') {
flat(v, s);
}
else {
result.push(s.join("."));
}
});
};
flat(source, []);
return result;
};