-
Notifications
You must be signed in to change notification settings - Fork 15
/
MatchOperation.ts
62 lines (49 loc) · 2.35 KB
/
MatchOperation.ts
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
import * as jsonpath from "jsonpath";
import * as jsonPtr from "json-ptr";
import Operation from "./Operation";
export default class MatchOperation extends Operation {
name() {
return "match";
}
processInArray(keyword: string, source: any, sourceArray: any[], sourceArrayIndex: number, resultArray: any[], resultArrayIndex: number, target: any[]) {
const keywordValue: MatchKeywordValue = source[keyword];
let matchedResultArrayIndex: number;
// Handle $match.index
if (keywordValue.index !== undefined) {
matchedResultArrayIndex = keywordValue.index === "-" ? resultArray.length - 1 : keywordValue.index;
}
// Handle $match.query
else if (keywordValue.query !== undefined) {
// Try to find a matching item in the result
const path = jsonpath.paths(resultArray, keywordValue.query)[0];
matchedResultArrayIndex = path !== undefined ? path[1] as number : undefined;
}
// Handle $match.path
else if (keywordValue.path !== undefined) {
// Try to find a matching item in the result
if (jsonPtr.get(resultArray, keywordValue.path) !== undefined) {
[matchedResultArrayIndex] = jsonPtr.decodePointer(keywordValue.path)[0];
}
}
// Ignore the item if no match found
if (matchedResultArrayIndex === undefined || resultArray[matchedResultArrayIndex] === undefined) {
return {resultArray, resultArrayIndex};
}
// Process result array item
const result = this._processor.processArrayItem(keywordValue.value, sourceArray, sourceArrayIndex, resultArray, matchedResultArrayIndex, target);
// Check if an array item has been inserted or removed below or at the current array item
if (matchedResultArrayIndex <= resultArrayIndex) {
resultArrayIndex += result.resultArrayIndex - matchedResultArrayIndex;
}
return {resultArray: result.resultArray, resultArrayIndex};
}
}
/*
* TYPES
*/
export interface MatchKeywordValue {
"index"?: number | "-"; // the index to match against, use '-' to match on the last item
"path"?: string; // the json pointer to match against
"query"?: string; // the json path to match against
"value": any; // the operation or value to use if a match is found
}