@labdigital/commercetools-mock 2.17.1 → 2.18.0
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/index.cjs +4186 -3974
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +266 -413
- package/dist/index.d.ts +266 -413
- package/dist/index.js +4186 -3974
- package/dist/index.js.map +1 -1
- package/package.json +44 -46
- package/src/constants.ts +2 -2
- package/src/ctMock.test.ts +11 -11
- package/src/ctMock.ts +141 -127
- package/src/deprecation.ts +8 -0
- package/src/exceptions.ts +17 -15
- package/src/helpers.ts +32 -32
- package/src/index.test.ts +128 -128
- package/src/index.ts +3 -3
- package/src/lib/expandParser.ts +13 -13
- package/src/lib/haversine.test.ts +9 -9
- package/src/lib/haversine.ts +11 -11
- package/src/lib/masking.ts +11 -11
- package/src/lib/parser.ts +2 -2
- package/src/lib/password.ts +23 -3
- package/src/lib/predicateParser.test.ts +185 -183
- package/src/lib/predicateParser.ts +234 -234
- package/src/lib/projectionSearchFilter.test.ts +103 -101
- package/src/lib/projectionSearchFilter.ts +152 -150
- package/src/lib/proxy.ts +5 -5
- package/src/oauth/errors.ts +4 -4
- package/src/oauth/helpers.ts +6 -6
- package/src/oauth/server.test.ts +86 -86
- package/src/oauth/server.ts +158 -144
- package/src/oauth/store.ts +44 -43
- package/src/priceSelector.test.ts +35 -35
- package/src/priceSelector.ts +30 -30
- package/src/product-projection-search.ts +136 -134
- package/src/projectAPI.test.ts +7 -7
- package/src/projectAPI.ts +24 -22
- package/src/repositories/abstract.ts +168 -116
- package/src/repositories/associate-role.ts +90 -77
- package/src/repositories/attribute-group.ts +51 -40
- package/src/repositories/business-unit.ts +168 -148
- package/src/repositories/cart/actions.ts +489 -0
- package/src/repositories/cart/helpers.ts +30 -0
- package/src/repositories/cart/index.ts +180 -0
- package/src/repositories/cart-discount/actions.ts +148 -0
- package/src/repositories/cart-discount/index.ts +86 -0
- package/src/repositories/category/actions.ts +231 -0
- package/src/repositories/category/index.ts +52 -0
- package/src/repositories/channel.ts +88 -90
- package/src/repositories/custom-object.ts +46 -45
- package/src/repositories/customer/actions.ts +165 -0
- package/src/repositories/customer/index.ts +79 -0
- package/src/repositories/customer-group.ts +66 -55
- package/src/repositories/discount-code/actions.ts +149 -0
- package/src/repositories/discount-code/index.ts +50 -0
- package/src/repositories/errors.ts +10 -10
- package/src/repositories/extension.ts +64 -62
- package/src/repositories/helpers.ts +117 -118
- package/src/repositories/index.ts +80 -79
- package/src/repositories/inventory-entry/actions.ts +84 -0
- package/src/repositories/inventory-entry/index.ts +44 -0
- package/src/repositories/my-customer.ts +114 -0
- package/src/repositories/my-order.ts +8 -8
- package/src/repositories/order/actions.ts +281 -0
- package/src/repositories/{order.test.ts → order/index.test.ts} +77 -77
- package/src/repositories/order/index.ts +260 -0
- package/src/repositories/order-edit.ts +10 -23
- package/src/repositories/payment/actions.ts +305 -0
- package/src/repositories/payment/helpers.ts +17 -0
- package/src/repositories/payment/index.ts +56 -0
- package/src/repositories/product/actions.ts +943 -0
- package/src/repositories/product/helpers.ts +98 -0
- package/src/repositories/product/index.ts +130 -0
- package/src/repositories/product-discount.ts +127 -117
- package/src/repositories/product-projection.ts +56 -62
- package/src/repositories/product-selection.ts +31 -28
- package/src/repositories/product-type.ts +136 -134
- package/src/repositories/project.ts +133 -118
- package/src/repositories/quote-request.ts +7 -19
- package/src/repositories/quote.ts +7 -22
- package/src/repositories/review.ts +13 -26
- package/src/repositories/shipping-method/actions.ts +198 -0
- package/src/repositories/shipping-method/helpers.ts +10 -0
- package/src/repositories/shipping-method/index.ts +138 -0
- package/src/repositories/shopping-list/actions.ts +295 -0
- package/src/repositories/shopping-list/index.ts +122 -0
- package/src/repositories/staged-quote.ts +7 -20
- package/src/repositories/standalone-price.ts +57 -44
- package/src/repositories/state.ts +113 -68
- package/src/repositories/store.ts +106 -94
- package/src/repositories/subscription.ts +46 -22
- package/src/repositories/tax-category/actions.ts +94 -0
- package/src/repositories/tax-category/helpers.ts +8 -0
- package/src/repositories/tax-category/index.ts +25 -0
- package/src/repositories/type/actions.ts +162 -0
- package/src/repositories/type/index.ts +24 -0
- package/src/repositories/zone.ts +62 -58
- package/src/server.ts +9 -9
- package/src/services/abstract.ts +75 -72
- package/src/services/associate-roles.test.ts +27 -27
- package/src/services/associate-roles.ts +7 -7
- package/src/services/attribute-group.ts +7 -7
- package/src/services/business-units.test.ts +28 -28
- package/src/services/business-units.ts +7 -7
- package/src/services/cart-discount.test.ts +199 -199
- package/src/services/cart-discount.ts +7 -7
- package/src/services/cart.test.ts +261 -261
- package/src/services/cart.ts +22 -21
- package/src/services/category.test.ts +121 -121
- package/src/services/category.ts +7 -7
- package/src/services/channel.ts +7 -7
- package/src/services/custom-object.test.ts +130 -130
- package/src/services/custom-object.ts +34 -31
- package/src/services/customer-group.ts +7 -7
- package/src/services/customer.test.ts +205 -205
- package/src/services/customer.ts +23 -36
- package/src/services/discount-code.ts +7 -7
- package/src/services/extension.ts +7 -7
- package/src/services/index.ts +85 -81
- package/src/services/inventory-entry.test.ts +106 -106
- package/src/services/inventory-entry.ts +7 -7
- package/src/services/my-cart.test.ts +56 -56
- package/src/services/my-cart.ts +20 -20
- package/src/services/my-customer.test.ts +155 -104
- package/src/services/my-customer.ts +61 -75
- package/src/services/my-order.ts +16 -16
- package/src/services/my-payment.test.ts +40 -40
- package/src/services/my-payment.ts +7 -7
- package/src/services/my-shopping-list.ts +7 -7
- package/src/services/order.test.ts +243 -243
- package/src/services/order.ts +23 -18
- package/src/services/payment.test.ts +40 -40
- package/src/services/payment.ts +7 -7
- package/src/services/product-discount.ts +7 -7
- package/src/services/product-projection.test.ts +190 -190
- package/src/services/product-projection.ts +34 -32
- package/src/services/product-selection.test.ts +19 -19
- package/src/services/product-selection.ts +7 -7
- package/src/services/product-type.test.ts +38 -38
- package/src/services/product-type.ts +7 -7
- package/src/services/product.test.ts +658 -656
- package/src/services/product.ts +7 -7
- package/src/services/project.test.ts +24 -24
- package/src/services/project.ts +17 -17
- package/src/services/reviews.ts +7 -7
- package/src/services/shipping-method.test.ts +78 -78
- package/src/services/shipping-method.ts +16 -16
- package/src/services/shopping-list.test.ts +170 -170
- package/src/services/shopping-list.ts +7 -7
- package/src/services/standalone-price.test.ts +112 -112
- package/src/services/standalone-price.ts +7 -7
- package/src/services/state.test.ts +30 -30
- package/src/services/state.ts +7 -7
- package/src/services/store.test.ts +40 -40
- package/src/services/store.ts +7 -7
- package/src/services/subscription.ts +7 -7
- package/src/services/tax-category.test.ts +43 -43
- package/src/services/tax-category.ts +7 -7
- package/src/services/type.ts +7 -7
- package/src/services/zone.ts +7 -7
- package/src/shippingCalculator.test.ts +43 -43
- package/src/shippingCalculator.ts +23 -23
- package/src/storage/abstract.ts +36 -34
- package/src/storage/in-memory.ts +237 -233
- package/src/storage/index.ts +2 -2
- package/src/types.ts +91 -91
- package/src/repositories/cart-discount.ts +0 -219
- package/src/repositories/cart.ts +0 -659
- package/src/repositories/category.ts +0 -256
- package/src/repositories/customer.ts +0 -228
- package/src/repositories/discount-code.ts +0 -181
- package/src/repositories/inventory-entry.ts +0 -109
- package/src/repositories/order.ts +0 -514
- package/src/repositories/payment.ts +0 -342
- package/src/repositories/product.ts +0 -1106
- package/src/repositories/shipping-method.ts +0 -312
- package/src/repositories/shopping-list.ts +0 -392
- package/src/repositories/tax-category.ts +0 -111
- package/src/repositories/type.ts +0 -172
|
@@ -4,145 +4,145 @@
|
|
|
4
4
|
*
|
|
5
5
|
* See https://docs.commercetools.com/api/predicates/query
|
|
6
6
|
*/
|
|
7
|
-
import { haversineDistance } from
|
|
8
|
-
import { Lexer, Parser, type ITokenPosition } from
|
|
7
|
+
import { haversineDistance } from "./haversine";
|
|
8
|
+
import { Lexer, Parser, type ITokenPosition } from "./parser";
|
|
9
9
|
|
|
10
10
|
export class PredicateError {
|
|
11
|
-
message: string
|
|
11
|
+
message: string;
|
|
12
12
|
|
|
13
13
|
constructor(message: string) {
|
|
14
|
-
this.message = message
|
|
14
|
+
this.message = message;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
type MatchFunc = (target: any, variables: VariableMap) => boolean
|
|
18
|
+
type MatchFunc = (target: any, variables: VariableMap) => boolean;
|
|
19
19
|
type VariableMap = {
|
|
20
|
-
[key: string]: any
|
|
21
|
-
}
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
22
|
|
|
23
23
|
export const matchesPredicate = (
|
|
24
24
|
predicate: string | string[] | undefined,
|
|
25
25
|
target: any,
|
|
26
|
-
variables?: VariableMap
|
|
26
|
+
variables?: VariableMap,
|
|
27
27
|
): boolean => {
|
|
28
28
|
if (!predicate) {
|
|
29
|
-
return true
|
|
29
|
+
return true;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
if (Array.isArray(predicate)) {
|
|
33
33
|
return predicate.every((item) => {
|
|
34
|
-
const func = generateMatchFunc(item)
|
|
35
|
-
return func(target, variables ?? {})
|
|
36
|
-
})
|
|
34
|
+
const func = generateMatchFunc(item);
|
|
35
|
+
return func(target, variables ?? {});
|
|
36
|
+
});
|
|
37
37
|
} else {
|
|
38
|
-
const func = generateMatchFunc(predicate)
|
|
39
|
-
return func(target, variables ?? {})
|
|
38
|
+
const func = generateMatchFunc(predicate);
|
|
39
|
+
return func(target, variables ?? {});
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
};
|
|
42
42
|
|
|
43
43
|
export const parseQueryExpression = (
|
|
44
|
-
predicate: string | string[]
|
|
44
|
+
predicate: string | string[],
|
|
45
45
|
): MatchFunc => {
|
|
46
46
|
if (Array.isArray(predicate)) {
|
|
47
|
-
const callbacks = predicate.map((item) => generateMatchFunc(item))
|
|
47
|
+
const callbacks = predicate.map((item) => generateMatchFunc(item));
|
|
48
48
|
return (target: any, variables: VariableMap) =>
|
|
49
|
-
callbacks.every((callback) => callback(target, variables))
|
|
49
|
+
callbacks.every((callback) => callback(target, variables));
|
|
50
50
|
} else {
|
|
51
|
-
return generateMatchFunc(predicate)
|
|
51
|
+
return generateMatchFunc(predicate);
|
|
52
52
|
}
|
|
53
|
-
}
|
|
53
|
+
};
|
|
54
54
|
|
|
55
55
|
type TypeSymbol = {
|
|
56
|
-
type:
|
|
57
|
-
value: any
|
|
58
|
-
pos?: ITokenPosition
|
|
59
|
-
}
|
|
56
|
+
type: "var" | "boolean" | "string" | "float" | "int" | "identifier";
|
|
57
|
+
value: any;
|
|
58
|
+
pos?: ITokenPosition;
|
|
59
|
+
};
|
|
60
60
|
|
|
61
61
|
const validateSymbol = (val: TypeSymbol) => {
|
|
62
62
|
if (!val.type) {
|
|
63
|
-
throw new PredicateError(
|
|
63
|
+
throw new PredicateError("Internal error");
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
if (val.type ===
|
|
67
|
-
const char = val.value.charAt(0)
|
|
68
|
-
const line = val.pos?.start.line
|
|
69
|
-
const column = val.pos?.start.column
|
|
66
|
+
if (val.type === "identifier") {
|
|
67
|
+
const char = val.value.charAt(0);
|
|
68
|
+
const line = val.pos?.start.line;
|
|
69
|
+
const column = val.pos?.start.column;
|
|
70
70
|
|
|
71
71
|
throw new PredicateError(
|
|
72
|
-
`Invalid input '${char}', expected input parameter or primitive value (line ${line}, column ${column})
|
|
73
|
-
)
|
|
72
|
+
`Invalid input '${char}', expected input parameter or primitive value (line ${line}, column ${column})`,
|
|
73
|
+
);
|
|
74
74
|
}
|
|
75
|
-
}
|
|
75
|
+
};
|
|
76
76
|
|
|
77
77
|
const resolveSymbol = (val: TypeSymbol, vars: VariableMap): any => {
|
|
78
|
-
if (val.type ===
|
|
78
|
+
if (val.type === "var") {
|
|
79
79
|
if (!(val.value in (vars ?? {}))) {
|
|
80
|
-
throw new PredicateError(`Missing parameter value for ${val.value}`)
|
|
80
|
+
throw new PredicateError(`Missing parameter value for ${val.value}`);
|
|
81
81
|
}
|
|
82
|
-
return vars[val.value]
|
|
82
|
+
return vars[val.value];
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
return val.value
|
|
86
|
-
}
|
|
85
|
+
return val.value;
|
|
86
|
+
};
|
|
87
87
|
|
|
88
88
|
const resolveValue = (obj: any, val: TypeSymbol): any => {
|
|
89
|
-
if (val.type !==
|
|
90
|
-
throw new PredicateError(
|
|
89
|
+
if (val.type !== "identifier") {
|
|
90
|
+
throw new PredicateError("Internal error");
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
if (!(val.value in obj)) {
|
|
94
94
|
if (Array.isArray(obj)) {
|
|
95
95
|
return Object.values(obj)
|
|
96
96
|
.filter((v) => val.value in v)
|
|
97
|
-
.map((v) => v[val.value])
|
|
97
|
+
.map((v) => v[val.value]);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// TODO: We don't really validate the shape of the object here. To actually
|
|
101
101
|
// match commercetools behaviour we should throw an error if the requested
|
|
102
102
|
// field doesn't exist (unless it's a map)
|
|
103
103
|
// throw new PredicateError(`The field '${val.value}' does not exist.`)
|
|
104
|
-
return undefined
|
|
104
|
+
return undefined;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
return obj[val.value]
|
|
108
|
-
}
|
|
107
|
+
return obj[val.value];
|
|
108
|
+
};
|
|
109
109
|
|
|
110
110
|
const getLexer = (value: string) =>
|
|
111
111
|
new Lexer(value)
|
|
112
112
|
|
|
113
|
-
.token(
|
|
114
|
-
.token(
|
|
115
|
-
.token(
|
|
116
|
-
|
|
117
|
-
.token(
|
|
118
|
-
.token(
|
|
119
|
-
.token(
|
|
120
|
-
.token(
|
|
121
|
-
.token(
|
|
122
|
-
.token(
|
|
123
|
-
.token(
|
|
124
|
-
.token(
|
|
125
|
-
.token(
|
|
126
|
-
|
|
127
|
-
.token(
|
|
128
|
-
.token(
|
|
129
|
-
.token(
|
|
130
|
-
.token(
|
|
131
|
-
.token(
|
|
132
|
-
.token(
|
|
133
|
-
.token(
|
|
134
|
-
|
|
135
|
-
.token(
|
|
136
|
-
.token(
|
|
137
|
-
.token(
|
|
138
|
-
.token(
|
|
139
|
-
.token(
|
|
140
|
-
.token(
|
|
141
|
-
.token(
|
|
142
|
-
.token(
|
|
143
|
-
.token(
|
|
113
|
+
.token("AND", /and(?![-_a-z0-9]+)/i)
|
|
114
|
+
.token("OR", /or(?![-_a-z0-9]+)/i)
|
|
115
|
+
.token("NOT", /not(?![-_a-z0-9]+)/i)
|
|
116
|
+
|
|
117
|
+
.token("WITHIN", /within(?![-_a-z0-9]+)/i)
|
|
118
|
+
.token("IN", /in(?![-_a-z0-9]+)/i)
|
|
119
|
+
.token("MATCHES_IGNORE_CASE", /matches\s+ignore\s+case(?![-_a-z0-9]+)/i)
|
|
120
|
+
.token("CONTAINS", /contains(?![-_a-z0-9]+)/i)
|
|
121
|
+
.token("ALL", /all(?![-_a-z0-9]+)/i)
|
|
122
|
+
.token("ANY", /any(?![-_a-z0-9]+)/i)
|
|
123
|
+
.token("EMPTY", /empty(?![-_a-z0-9]+)/i)
|
|
124
|
+
.token("IS", /is(?![-_a-z0-9]+)/i)
|
|
125
|
+
.token("DEFINED", /defined(?![-_a-z0-9]+)/i)
|
|
126
|
+
|
|
127
|
+
.token("FLOAT", /\d+\.\d+/)
|
|
128
|
+
.token("INT", /\d+/)
|
|
129
|
+
.token("VARIABLE", /:([-_A-Za-z0-9]+)/)
|
|
130
|
+
.token("BOOLEAN", /(true|false)/)
|
|
131
|
+
.token("IDENTIFIER", /[-_A-Za-z0-9]+/)
|
|
132
|
+
.token("STRING", /"((?:\\.|[^"\\])*)"/)
|
|
133
|
+
.token("STRING", /'((?:\\.|[^'\\])*)'/)
|
|
134
|
+
|
|
135
|
+
.token("COMMA", ",")
|
|
136
|
+
.token("(", "(")
|
|
137
|
+
.token(")", ")")
|
|
138
|
+
.token(">=", ">=")
|
|
139
|
+
.token("<=", "<=")
|
|
140
|
+
.token(">", ">")
|
|
141
|
+
.token("<", "<")
|
|
142
|
+
.token("!=", "!=")
|
|
143
|
+
.token("=", "=")
|
|
144
144
|
.token('"', '"')
|
|
145
|
-
.token(
|
|
145
|
+
.token("WS", /\s+/, true); // skip
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
* This function converts a query expression in to a callable which returns a
|
|
@@ -152,228 +152,228 @@ const getLexer = (value: string) =>
|
|
|
152
152
|
* straight-forward to add a query cache (lru-cache)
|
|
153
153
|
*/
|
|
154
154
|
const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
155
|
-
const lexer = getLexer(predicate)
|
|
155
|
+
const lexer = getLexer(predicate);
|
|
156
156
|
const parser = new Parser(lexer)
|
|
157
157
|
.builder()
|
|
158
158
|
.nud(
|
|
159
|
-
|
|
159
|
+
"IDENTIFIER",
|
|
160
160
|
100,
|
|
161
161
|
(t) =>
|
|
162
162
|
({
|
|
163
|
-
type:
|
|
163
|
+
type: "identifier",
|
|
164
164
|
value: t.token.match,
|
|
165
165
|
pos: t.token.strpos(),
|
|
166
|
-
}) as TypeSymbol
|
|
166
|
+
}) as TypeSymbol,
|
|
167
167
|
)
|
|
168
168
|
.nud(
|
|
169
|
-
|
|
169
|
+
"BOOLEAN",
|
|
170
170
|
1,
|
|
171
171
|
(t) =>
|
|
172
172
|
({
|
|
173
|
-
type:
|
|
174
|
-
value: t.token.match ===
|
|
173
|
+
type: "boolean",
|
|
174
|
+
value: t.token.match === "true" ? true : false,
|
|
175
175
|
pos: t.token.strpos(),
|
|
176
|
-
}) as TypeSymbol
|
|
176
|
+
}) as TypeSymbol,
|
|
177
177
|
)
|
|
178
178
|
.nud(
|
|
179
|
-
|
|
179
|
+
"VARIABLE",
|
|
180
180
|
100,
|
|
181
181
|
(t) =>
|
|
182
182
|
({
|
|
183
|
-
type:
|
|
183
|
+
type: "var",
|
|
184
184
|
// @ts-ignore
|
|
185
185
|
value: t.token.groups[1],
|
|
186
186
|
pos: t.token.strpos(),
|
|
187
|
-
}) as TypeSymbol
|
|
187
|
+
}) as TypeSymbol,
|
|
188
188
|
)
|
|
189
189
|
.nud(
|
|
190
|
-
|
|
190
|
+
"STRING",
|
|
191
191
|
100,
|
|
192
192
|
(t) =>
|
|
193
193
|
({
|
|
194
|
-
type:
|
|
194
|
+
type: "string",
|
|
195
195
|
// @ts-ignore
|
|
196
196
|
value: t.token.groups[1],
|
|
197
197
|
pos: t.token.strpos(),
|
|
198
|
-
}) as TypeSymbol
|
|
198
|
+
}) as TypeSymbol,
|
|
199
199
|
)
|
|
200
200
|
.nud(
|
|
201
|
-
|
|
201
|
+
"INT",
|
|
202
202
|
1,
|
|
203
203
|
(t) =>
|
|
204
204
|
({
|
|
205
|
-
type:
|
|
205
|
+
type: "int",
|
|
206
206
|
value: parseInt(t.token.match, 10),
|
|
207
207
|
pos: t.token.strpos(),
|
|
208
|
-
}) as TypeSymbol
|
|
208
|
+
}) as TypeSymbol,
|
|
209
209
|
)
|
|
210
210
|
.nud(
|
|
211
|
-
|
|
211
|
+
"FLOAT",
|
|
212
212
|
1,
|
|
213
213
|
(t) =>
|
|
214
214
|
({
|
|
215
|
-
type:
|
|
215
|
+
type: "float",
|
|
216
216
|
value: parseFloat(t.token.match),
|
|
217
217
|
pos: t.token.strpos(),
|
|
218
|
-
}) as TypeSymbol
|
|
218
|
+
}) as TypeSymbol,
|
|
219
219
|
)
|
|
220
|
-
.nud(
|
|
221
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
222
|
-
return (obj: any) => !expr(obj)
|
|
220
|
+
.nud("NOT", 100, ({ bp }) => {
|
|
221
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
222
|
+
return (obj: any) => !expr(obj);
|
|
223
223
|
})
|
|
224
|
-
.nud(
|
|
225
|
-
.nud(
|
|
224
|
+
.nud("EMPTY", 10, ({ bp }) => "empty")
|
|
225
|
+
.nud("DEFINED", 10, ({ bp }) => "defined")
|
|
226
226
|
|
|
227
|
-
.led(
|
|
228
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
229
|
-
return (obj: any) => left(obj) && expr(obj)
|
|
227
|
+
.led("AND", 5, ({ left, bp }) => {
|
|
228
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
229
|
+
return (obj: any) => left(obj) && expr(obj);
|
|
230
230
|
})
|
|
231
|
-
.led(
|
|
232
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
233
|
-
return (obj: any, vars: object) => left(obj, vars) || expr(obj, vars)
|
|
231
|
+
.led("OR", 5, ({ left, token, bp }) => {
|
|
232
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
233
|
+
return (obj: any, vars: object) => left(obj, vars) || expr(obj, vars);
|
|
234
234
|
})
|
|
235
|
-
.led(
|
|
236
|
-
const expr: any = parser.parse({ terminals: [bp - 1] })
|
|
235
|
+
.led("COMMA", 1, ({ left, token, bp }) => {
|
|
236
|
+
const expr: any = parser.parse({ terminals: [bp - 1] });
|
|
237
237
|
if (Array.isArray(expr)) {
|
|
238
|
-
return [left, ...expr]
|
|
238
|
+
return [left, ...expr];
|
|
239
239
|
} else {
|
|
240
|
-
return [left, expr]
|
|
240
|
+
return [left, expr];
|
|
241
241
|
}
|
|
242
242
|
})
|
|
243
|
-
.nud(
|
|
244
|
-
const expr: any = parser.parse({ terminals: [
|
|
245
|
-
return expr
|
|
243
|
+
.nud("(", 100, (t) => {
|
|
244
|
+
const expr: any = parser.parse({ terminals: [")"] });
|
|
245
|
+
return expr;
|
|
246
246
|
})
|
|
247
|
-
.led(
|
|
248
|
-
const expr = parser.parse()
|
|
249
|
-
lexer.expect(
|
|
247
|
+
.led("(", 100, ({ left, bp }) => {
|
|
248
|
+
const expr = parser.parse();
|
|
249
|
+
lexer.expect(")");
|
|
250
250
|
return (obj: any, vars: object) => {
|
|
251
251
|
if (Array.isArray(obj)) {
|
|
252
252
|
return obj.some((item) => {
|
|
253
|
-
const value = resolveValue(item, left)
|
|
253
|
+
const value = resolveValue(item, left);
|
|
254
254
|
if (value) {
|
|
255
|
-
return expr(value, vars)
|
|
255
|
+
return expr(value, vars);
|
|
256
256
|
}
|
|
257
|
-
return false
|
|
258
|
-
})
|
|
257
|
+
return false;
|
|
258
|
+
});
|
|
259
259
|
} else {
|
|
260
|
-
const value = resolveValue(obj, left)
|
|
260
|
+
const value = resolveValue(obj, left);
|
|
261
261
|
if (value) {
|
|
262
|
-
return expr(value, vars)
|
|
262
|
+
return expr(value, vars);
|
|
263
263
|
}
|
|
264
|
-
return false
|
|
264
|
+
return false;
|
|
265
265
|
}
|
|
266
|
-
}
|
|
266
|
+
};
|
|
267
267
|
})
|
|
268
|
-
.bp(
|
|
269
|
-
.led(
|
|
270
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
271
|
-
validateSymbol(expr)
|
|
268
|
+
.bp(")", 0)
|
|
269
|
+
.led("=", 20, ({ left, bp }) => {
|
|
270
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
271
|
+
validateSymbol(expr);
|
|
272
272
|
|
|
273
273
|
return (obj: any, vars: VariableMap) => {
|
|
274
274
|
if (Array.isArray(obj)) {
|
|
275
275
|
return obj.some((item) => {
|
|
276
|
-
const value = resolveValue(item, left)
|
|
277
|
-
const other = resolveSymbol(expr, vars)
|
|
276
|
+
const value = resolveValue(item, left);
|
|
277
|
+
const other = resolveSymbol(expr, vars);
|
|
278
278
|
if (Array.isArray(value)) {
|
|
279
|
-
return !!value.some((elem) => elem === other)
|
|
279
|
+
return !!value.some((elem) => elem === other);
|
|
280
280
|
}
|
|
281
|
-
return value === other
|
|
282
|
-
})
|
|
281
|
+
return value === other;
|
|
282
|
+
});
|
|
283
283
|
} else {
|
|
284
|
-
const resolvedValue = resolveValue(obj, left)
|
|
285
|
-
const resolvedSymbol = resolveSymbol(expr, vars)
|
|
284
|
+
const resolvedValue = resolveValue(obj, left);
|
|
285
|
+
const resolvedSymbol = resolveSymbol(expr, vars);
|
|
286
286
|
if (Array.isArray(resolvedValue)) {
|
|
287
|
-
return !!resolvedValue.some((elem) => elem === resolvedSymbol)
|
|
287
|
+
return !!resolvedValue.some((elem) => elem === resolvedSymbol);
|
|
288
288
|
}
|
|
289
|
-
return resolvedValue === resolvedSymbol
|
|
289
|
+
return resolvedValue === resolvedSymbol;
|
|
290
290
|
}
|
|
291
|
-
}
|
|
291
|
+
};
|
|
292
292
|
})
|
|
293
|
-
.led(
|
|
294
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
295
|
-
validateSymbol(expr)
|
|
293
|
+
.led("!=", 20, ({ left, bp }) => {
|
|
294
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
295
|
+
validateSymbol(expr);
|
|
296
296
|
return (obj: any, vars: VariableMap) =>
|
|
297
|
-
resolveValue(obj, left) !== resolveSymbol(expr, vars)
|
|
297
|
+
resolveValue(obj, left) !== resolveSymbol(expr, vars);
|
|
298
298
|
})
|
|
299
|
-
.led(
|
|
300
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
301
|
-
validateSymbol(expr)
|
|
299
|
+
.led(">", 20, ({ left, bp }) => {
|
|
300
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
301
|
+
validateSymbol(expr);
|
|
302
302
|
|
|
303
303
|
return (obj: any, vars: object) =>
|
|
304
|
-
resolveValue(obj, left) > resolveSymbol(expr, vars)
|
|
304
|
+
resolveValue(obj, left) > resolveSymbol(expr, vars);
|
|
305
305
|
})
|
|
306
|
-
.led(
|
|
307
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
308
|
-
validateSymbol(expr)
|
|
306
|
+
.led(">=", 20, ({ left, bp }) => {
|
|
307
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
308
|
+
validateSymbol(expr);
|
|
309
309
|
|
|
310
310
|
return (obj: any, vars: object) =>
|
|
311
|
-
resolveValue(obj, left) >= resolveSymbol(expr, vars)
|
|
311
|
+
resolveValue(obj, left) >= resolveSymbol(expr, vars);
|
|
312
312
|
})
|
|
313
|
-
.led(
|
|
314
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
315
|
-
validateSymbol(expr)
|
|
313
|
+
.led("<", 20, ({ left, bp }) => {
|
|
314
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
315
|
+
validateSymbol(expr);
|
|
316
316
|
|
|
317
317
|
return (obj: any, vars: object) =>
|
|
318
|
-
resolveValue(obj, left) < resolveSymbol(expr, vars)
|
|
318
|
+
resolveValue(obj, left) < resolveSymbol(expr, vars);
|
|
319
319
|
})
|
|
320
|
-
.led(
|
|
321
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
322
|
-
validateSymbol(expr)
|
|
320
|
+
.led("<=", 20, ({ left, bp }) => {
|
|
321
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
322
|
+
validateSymbol(expr);
|
|
323
323
|
|
|
324
324
|
return (obj: any, vars: object) =>
|
|
325
|
-
resolveValue(obj, left) <= resolveSymbol(expr, vars)
|
|
325
|
+
resolveValue(obj, left) <= resolveSymbol(expr, vars);
|
|
326
326
|
})
|
|
327
|
-
.led(
|
|
328
|
-
let invert = false
|
|
327
|
+
.led("IS", 20, ({ left, bp }) => {
|
|
328
|
+
let invert = false;
|
|
329
329
|
|
|
330
330
|
// Peek if this is a `is not` statement
|
|
331
|
-
const next = lexer.peek()
|
|
332
|
-
if (next.type ===
|
|
333
|
-
invert = true
|
|
334
|
-
lexer.next()
|
|
331
|
+
const next = lexer.peek();
|
|
332
|
+
if (next.type === "NOT") {
|
|
333
|
+
invert = true;
|
|
334
|
+
lexer.next();
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
-
const expr: any = parser.parse({ terminals: [bp - 1] })
|
|
337
|
+
const expr: any = parser.parse({ terminals: [bp - 1] });
|
|
338
338
|
|
|
339
339
|
switch (expr) {
|
|
340
|
-
case
|
|
340
|
+
case "empty": {
|
|
341
341
|
if (!invert) {
|
|
342
342
|
return (obj: any, vars: VariableMap) => {
|
|
343
|
-
const val = resolveValue(obj, left)
|
|
344
|
-
return val.length === 0
|
|
345
|
-
}
|
|
343
|
+
const val = resolveValue(obj, left);
|
|
344
|
+
return val.length === 0;
|
|
345
|
+
};
|
|
346
346
|
} else {
|
|
347
347
|
return (obj: any, vars: VariableMap) => {
|
|
348
|
-
const val = resolveValue(obj, left)
|
|
349
|
-
return val.length !== 0
|
|
350
|
-
}
|
|
348
|
+
const val = resolveValue(obj, left);
|
|
349
|
+
return val.length !== 0;
|
|
350
|
+
};
|
|
351
351
|
}
|
|
352
352
|
}
|
|
353
|
-
case
|
|
353
|
+
case "defined": {
|
|
354
354
|
if (!invert) {
|
|
355
355
|
return (obj: any, vars: VariableMap) => {
|
|
356
|
-
const val = resolveValue(obj, left)
|
|
357
|
-
return val !== undefined
|
|
358
|
-
}
|
|
356
|
+
const val = resolveValue(obj, left);
|
|
357
|
+
return val !== undefined;
|
|
358
|
+
};
|
|
359
359
|
} else {
|
|
360
360
|
return (obj: any, vars: VariableMap) => {
|
|
361
|
-
const val = resolveValue(obj, left)
|
|
362
|
-
return val === undefined
|
|
363
|
-
}
|
|
361
|
+
const val = resolveValue(obj, left);
|
|
362
|
+
return val === undefined;
|
|
363
|
+
};
|
|
364
364
|
}
|
|
365
365
|
}
|
|
366
366
|
default: {
|
|
367
|
-
throw new Error(
|
|
367
|
+
throw new Error("Unexpected");
|
|
368
368
|
}
|
|
369
369
|
}
|
|
370
370
|
})
|
|
371
|
-
.led(
|
|
372
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
371
|
+
.led("IN", 20, ({ left, bp }) => {
|
|
372
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
373
373
|
return (obj: any, vars: object) => {
|
|
374
|
-
let symbols = expr
|
|
374
|
+
let symbols = expr;
|
|
375
375
|
if (!Array.isArray(symbols)) {
|
|
376
|
-
symbols = [expr]
|
|
376
|
+
symbols = [expr];
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
// The expression can be a list of variables, like
|
|
@@ -381,45 +381,45 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
381
381
|
// containing a list, like :values.
|
|
382
382
|
// So to support both we just flatten the list.
|
|
383
383
|
const inValues = symbols.flatMap((item: TypeSymbol) =>
|
|
384
|
-
resolveSymbol(item, vars)
|
|
385
|
-
)
|
|
386
|
-
const value = resolveValue(obj, left)
|
|
387
|
-
return inValues.includes(value)
|
|
388
|
-
}
|
|
384
|
+
resolveSymbol(item, vars),
|
|
385
|
+
);
|
|
386
|
+
const value = resolveValue(obj, left);
|
|
387
|
+
return inValues.includes(value);
|
|
388
|
+
};
|
|
389
389
|
})
|
|
390
|
-
.led(
|
|
391
|
-
const expr = parser.parse({ terminals: [bp - 1] })
|
|
392
|
-
validateSymbol(expr)
|
|
390
|
+
.led("MATCHES_IGNORE_CASE", 20, ({ left, bp }) => {
|
|
391
|
+
const expr = parser.parse({ terminals: [bp - 1] });
|
|
392
|
+
validateSymbol(expr);
|
|
393
393
|
|
|
394
394
|
return (obj: any, vars: VariableMap) => {
|
|
395
|
-
const value = resolveValue(obj, left)
|
|
396
|
-
const other = resolveSymbol(expr, vars)
|
|
395
|
+
const value = resolveValue(obj, left);
|
|
396
|
+
const other = resolveSymbol(expr, vars);
|
|
397
397
|
|
|
398
|
-
if (typeof value !=
|
|
398
|
+
if (typeof value != "string") {
|
|
399
399
|
throw new PredicateError(
|
|
400
|
-
`The field '${left.value}' does not support this expression
|
|
401
|
-
)
|
|
400
|
+
`The field '${left.value}' does not support this expression.`,
|
|
401
|
+
);
|
|
402
402
|
}
|
|
403
|
-
return value.toLowerCase() === other.toLowerCase()
|
|
404
|
-
}
|
|
403
|
+
return value.toLowerCase() === other.toLowerCase();
|
|
404
|
+
};
|
|
405
405
|
})
|
|
406
|
-
.led(
|
|
407
|
-
const type = lexer.next()
|
|
406
|
+
.led("WITHIN", 20, ({ left, bp }) => {
|
|
407
|
+
const type = lexer.next();
|
|
408
408
|
|
|
409
|
-
if (type.match !==
|
|
409
|
+
if (type.match !== "circle") {
|
|
410
410
|
throw new PredicateError(
|
|
411
|
-
`Invalid input '${type.match}', expected circle
|
|
412
|
-
)
|
|
411
|
+
`Invalid input '${type.match}', expected circle`,
|
|
412
|
+
);
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
-
lexer.expect(
|
|
416
|
-
const expr = parser.parse({ terminals: [
|
|
415
|
+
lexer.expect("(");
|
|
416
|
+
const expr = parser.parse({ terminals: [")"] });
|
|
417
417
|
|
|
418
418
|
return (obj: any, vars: object) => {
|
|
419
|
-
const value = resolveValue(obj, left)
|
|
420
|
-
if (!value) return false
|
|
419
|
+
const value = resolveValue(obj, left);
|
|
420
|
+
if (!value) return false;
|
|
421
421
|
|
|
422
|
-
const maxDistance = resolveSymbol(expr[2], vars)
|
|
422
|
+
const maxDistance = resolveSymbol(expr[2], vars);
|
|
423
423
|
const distance = haversineDistance(
|
|
424
424
|
{
|
|
425
425
|
longitude: value[0],
|
|
@@ -428,50 +428,50 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
|
|
|
428
428
|
{
|
|
429
429
|
longitude: resolveSymbol(expr[0], vars),
|
|
430
430
|
latitude: resolveSymbol(expr[1], vars),
|
|
431
|
-
}
|
|
432
|
-
)
|
|
433
|
-
return distance <= maxDistance
|
|
434
|
-
}
|
|
431
|
+
},
|
|
432
|
+
);
|
|
433
|
+
return distance <= maxDistance;
|
|
434
|
+
};
|
|
435
435
|
})
|
|
436
|
-
.led(
|
|
437
|
-
const keyword = lexer.next()
|
|
436
|
+
.led("CONTAINS", 20, ({ left, bp }) => {
|
|
437
|
+
const keyword = lexer.next();
|
|
438
438
|
|
|
439
|
-
let expr = parser.parse()
|
|
439
|
+
let expr = parser.parse();
|
|
440
440
|
if (!Array.isArray(expr)) {
|
|
441
|
-
expr = [expr]
|
|
441
|
+
expr = [expr];
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
return (obj: any, vars: object) => {
|
|
445
|
-
const value = resolveValue(obj, left)
|
|
445
|
+
const value = resolveValue(obj, left);
|
|
446
446
|
|
|
447
447
|
if (!Array.isArray(value)) {
|
|
448
448
|
throw new PredicateError(
|
|
449
|
-
`The field '${left.value}' does not support this expression
|
|
450
|
-
)
|
|
449
|
+
`The field '${left.value}' does not support this expression.`,
|
|
450
|
+
);
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
-
const array = expr.map((item: TypeSymbol) => resolveSymbol(item, vars))
|
|
454
|
-
if (keyword.type ===
|
|
455
|
-
return array.every((item: any) => value.includes(item))
|
|
453
|
+
const array = expr.map((item: TypeSymbol) => resolveSymbol(item, vars));
|
|
454
|
+
if (keyword.type === "ALL") {
|
|
455
|
+
return array.every((item: any) => value.includes(item));
|
|
456
456
|
} else {
|
|
457
|
-
return array.some((item: any) => value.includes(item))
|
|
457
|
+
return array.some((item: any) => value.includes(item));
|
|
458
458
|
}
|
|
459
|
-
}
|
|
459
|
+
};
|
|
460
460
|
})
|
|
461
461
|
|
|
462
|
-
.build()
|
|
462
|
+
.build();
|
|
463
463
|
|
|
464
|
-
const result = parser.parse()
|
|
464
|
+
const result = parser.parse();
|
|
465
465
|
|
|
466
|
-
if (typeof result !==
|
|
467
|
-
const lines = predicate.split(
|
|
468
|
-
const column = lines[lines.length - 1].length
|
|
466
|
+
if (typeof result !== "function") {
|
|
467
|
+
const lines = predicate.split("\n");
|
|
468
|
+
const column = lines[lines.length - 1].length;
|
|
469
469
|
|
|
470
470
|
throw new PredicateError(
|
|
471
471
|
`Unexpected end of input, expected SphereIdentifierChar, comparison ` +
|
|
472
472
|
`operator, not, in, contains, is, within or matches` +
|
|
473
|
-
` (line ${lines.length}, column ${column})
|
|
474
|
-
)
|
|
473
|
+
` (line ${lines.length}, column ${column})`,
|
|
474
|
+
);
|
|
475
475
|
}
|
|
476
|
-
return result
|
|
477
|
-
}
|
|
476
|
+
return result;
|
|
477
|
+
};
|