-
-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathdecode.ts
More file actions
131 lines (128 loc) · 4.73 KB
/
decode.ts
File metadata and controls
131 lines (128 loc) · 4.73 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
119
120
121
122
123
124
125
126
127
128
129
130
131
import {OpAdd} from '../../op/OpAdd';
import {OpRemove} from '../../op/OpRemove';
import {OpReplace} from '../../op/OpReplace';
import {OpMove} from '../../op/OpMove';
import {OpCopy} from '../../op/OpCopy';
import {OpTest} from '../../op/OpTest';
import {OpFlip} from '../../op/OpFlip';
import {OpInc} from '../../op/OpInc';
import {OpStrIns} from '../../op/OpStrIns';
import {OpStrDel} from '../../op/OpStrDel';
import {OpSplit} from '../../op/OpSplit';
import {OpMerge} from '../../op/OpMerge';
import {OpExtend} from '../../op/OpExtend';
import {OpDefined} from '../../op/OpDefined';
import {OpUndefined} from '../../op/OpUndefined';
import {OpTestType} from '../../op/OpTestType';
import {OpTestString} from '../../op/OpTestString';
import {OpTestStringLen} from '../../op/OpTestStringLen';
import {OpContains} from '../../op/OpContains';
import {OpEnds} from '../../op/OpEnds';
import {OpStarts} from '../../op/OpStarts';
import {OpIn} from '../../op/OpIn';
import {OpLess} from '../../op/OpLess';
import {OpMore} from '../../op/OpMore';
import {OpAnd} from '../../op/OpAnd';
import {OpOr} from '../../op/OpOr';
import {OpNot} from '../../op/OpNot';
import {OpMatches} from '../../op/OpMatches';
import {OpType} from '../../op/OpType';
import {toPath} from '@jsonjoy.com/json-pointer';
import {createMatcherDefault} from '../../util';
import type {Op, PredicateOp} from '../../op';
import type {Operation} from './types';
import type {JsonPatchOptions} from '../../types';
export const operationToOp = (op: Operation, options: JsonPatchOptions): Op => {
switch (op.op) {
case 'add':
return new OpAdd(toPath(op.path), op.value);
case 'remove':
return new OpRemove(toPath(op.path), op.oldValue);
case 'replace':
return new OpReplace(toPath(op.path), op.value, op.oldValue);
case 'move':
return new OpMove(toPath(op.path), toPath(op.from));
case 'copy':
return new OpCopy(toPath(op.path), toPath(op.from));
case 'flip':
return new OpFlip(toPath(op.path));
case 'inc':
return new OpInc(toPath(op.path), op.inc);
case 'str_ins':
return new OpStrIns(toPath(op.path), op.pos, op.str);
case 'str_del':
return new OpStrDel(toPath(op.path), op.pos, op.str, op.len);
case 'split':
return new OpSplit(toPath(op.path), op.pos, op.props || null);
case 'merge':
return new OpMerge(toPath(op.path), op.pos, op.props || null);
case 'extend':
return new OpExtend(toPath(op.path), op.props, !!op.deleteNull);
default:
return operationToPredicateOp(op, options);
}
};
export const operationToPredicateOp = (op: Operation, options: JsonPatchOptions): PredicateOp => {
switch (op.op) {
case 'test':
return new OpTest(toPath(op.path), op.value, !!op.not);
case 'defined':
return new OpDefined(toPath(op.path));
case 'undefined':
return new OpUndefined(toPath(op.path));
case 'type':
return new OpType(toPath(op.path), op.value);
case 'test_type':
return new OpTestType(toPath(op.path), op.type);
case 'test_string':
return new OpTestString(toPath(op.path), op.pos, op.str, !!op.not);
case 'test_string_len':
return new OpTestStringLen(toPath(op.path), op.len, !!op.not);
case 'contains':
return new OpContains(toPath(op.path), op.value, !!op.ignore_case);
case 'ends':
return new OpEnds(toPath(op.path), op.value, !!op.ignore_case);
case 'starts':
return new OpStarts(toPath(op.path), op.value, !!op.ignore_case);
case 'matches':
return new OpMatches(toPath(op.path), op.value, !!op.ignore_case, options.createMatcher || createMatcherDefault);
case 'in':
return new OpIn(toPath(op.path), op.value);
case 'less':
return new OpLess(toPath(op.path), op.value);
case 'more':
return new OpMore(toPath(op.path), op.value);
case 'and': {
const path = toPath(op.path);
return new OpAnd(
path,
op.apply.map((x) => operationToPredicateOp({...x, path: [...path, ...toPath(x.path)]}, options)),
);
}
case 'or': {
const path = toPath(op.path);
return new OpOr(
path,
op.apply.map((x) => operationToPredicateOp({...x, path: [...path, ...toPath(x.path)]}, options)),
);
}
case 'not': {
const path = toPath(op.path);
return new OpNot(
path,
op.apply.map((x) => operationToPredicateOp({...x, path: [...path, ...toPath(x.path)]}, options)),
);
}
default:
throw new Error('OP_UNKNOWN');
}
};
export function decode(patch: readonly Operation[], options: JsonPatchOptions): Op[] {
const ops: Op[] = [];
const length = patch.length;
for (let i = 0; i < length; i++) {
const op = operationToOp(patch[i], options);
ops.push(op);
}
return ops;
}