@labdigital/commercetools-mock 1.5.0 → 1.6.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/README.md +5 -4
- package/dist/index.cjs +105 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -7
- package/dist/index.d.ts +29 -7
- package/dist/index.js +105 -17
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/constants.ts +2 -2
- package/src/ctMock.ts +176 -176
- package/src/exceptions.ts +10 -10
- package/src/helpers.ts +26 -26
- package/src/index.test.ts +173 -173
- package/src/index.ts +3 -3
- package/src/lib/expandParser.ts +19 -19
- package/src/lib/haversine.test.ts +13 -13
- package/src/lib/haversine.ts +14 -14
- package/src/lib/masking.ts +15 -15
- package/src/lib/parser.ts +2 -2
- package/src/lib/predicateParser.test.ts +204 -204
- package/src/lib/predicateParser.ts +398 -398
- package/src/lib/projectionSearchFilter.test.ts +168 -168
- package/src/lib/projectionSearchFilter.ts +272 -269
- package/src/lib/proxy.ts +8 -8
- package/src/oauth/errors.ts +4 -4
- package/src/oauth/helpers.ts +6 -6
- package/src/oauth/server.ts +103 -101
- package/src/oauth/store.ts +27 -27
- package/src/priceSelector.test.ts +68 -68
- package/src/priceSelector.ts +70 -70
- package/src/product-projection-search.ts +296 -296
- package/src/projectAPI.test.ts +3 -3
- package/src/projectAPI.ts +46 -46
- package/src/repositories/abstract.ts +190 -190
- package/src/repositories/associate-role.ts +10 -7
- package/src/repositories/attribute-group.ts +63 -8
- package/src/repositories/business-unit.ts +10 -7
- package/src/repositories/cart-discount.ts +134 -134
- package/src/repositories/cart.ts +517 -514
- package/src/repositories/category.ts +170 -167
- package/src/repositories/channel.ts +114 -111
- package/src/repositories/custom-object.ts +66 -63
- package/src/repositories/customer-group.ts +72 -69
- package/src/repositories/customer.ts +90 -90
- package/src/repositories/discount-code.ts +171 -168
- package/src/repositories/errors.ts +15 -15
- package/src/repositories/extension.ts +79 -76
- package/src/repositories/helpers.ts +180 -180
- package/src/repositories/index.ts +39 -39
- package/src/repositories/inventory-entry.ts +98 -95
- package/src/repositories/my-order.ts +11 -11
- package/src/repositories/order-edit.ts +29 -29
- package/src/repositories/order.test.ts +191 -191
- package/src/repositories/order.ts +393 -393
- package/src/repositories/payment.ts +155 -155
- package/src/repositories/product-discount.ts +149 -149
- package/src/repositories/product-projection.ts +116 -52
- package/src/repositories/product-selection.ts +31 -31
- package/src/repositories/product-type.ts +156 -156
- package/src/repositories/product.ts +600 -597
- package/src/repositories/project.ts +136 -135
- package/src/repositories/quote-request.ts +19 -19
- package/src/repositories/quote.ts +19 -19
- package/src/repositories/review.ts +24 -24
- package/src/repositories/shipping-method.ts +217 -217
- package/src/repositories/shopping-list.ts +49 -49
- package/src/repositories/staged-quote.ts +20 -20
- package/src/repositories/standalone-price.ts +72 -61
- package/src/repositories/state.ts +84 -84
- package/src/repositories/store.ts +114 -114
- package/src/repositories/subscription.ts +40 -40
- package/src/repositories/tax-category.ts +98 -98
- package/src/repositories/type.ts +157 -157
- package/src/repositories/zone.ts +71 -71
- package/src/server.ts +2 -2
- package/src/services/abstract.ts +173 -173
- package/src/services/attribute-group.ts +16 -0
- package/src/services/cart-discount.ts +8 -8
- package/src/services/cart.test.ts +409 -409
- package/src/services/cart.ts +50 -50
- package/src/services/category.test.ts +25 -25
- package/src/services/category.ts +8 -8
- package/src/services/channel.ts +8 -8
- package/src/services/custom-object.test.ts +184 -184
- package/src/services/custom-object.ts +48 -48
- package/src/services/customer-group.ts +8 -8
- package/src/services/customer.test.ts +151 -151
- package/src/services/customer.ts +27 -27
- package/src/services/discount-code.ts +8 -8
- package/src/services/extension.ts +8 -8
- package/src/services/index.ts +52 -44
- package/src/services/inventory-entry.test.ts +162 -162
- package/src/services/inventory-entry.ts +8 -8
- package/src/services/my-cart.test.ts +78 -78
- package/src/services/my-cart.ts +28 -28
- package/src/services/my-customer.test.ts +44 -44
- package/src/services/my-customer.ts +53 -53
- package/src/services/my-order.ts +20 -20
- package/src/services/my-payment.test.ts +65 -65
- package/src/services/my-payment.ts +8 -8
- package/src/services/order.test.ts +527 -527
- package/src/services/order.ts +31 -31
- package/src/services/payment.test.ts +65 -65
- package/src/services/payment.ts +8 -8
- package/src/services/product-discount.ts +8 -8
- package/src/services/product-projection.test.ts +492 -428
- package/src/services/product-projection.ts +32 -18
- package/src/services/product-type.test.ts +56 -56
- package/src/services/product-type.ts +8 -8
- package/src/services/product.test.ts +510 -510
- package/src/services/product.ts +8 -8
- package/src/services/project.ts +34 -34
- package/src/services/shipping-method.test.ts +81 -81
- package/src/services/shipping-method.ts +12 -12
- package/src/services/shopping-list.ts +8 -8
- package/src/services/standalone-price.test.ts +256 -256
- package/src/services/standalone-price.ts +8 -8
- package/src/services/state.test.ts +42 -42
- package/src/services/state.ts +8 -8
- package/src/services/store.test.ts +57 -57
- package/src/services/store.ts +8 -8
- package/src/services/subscription.ts +8 -8
- package/src/services/tax-category.test.ts +61 -61
- package/src/services/tax-category.ts +8 -8
- package/src/services/type.ts +8 -8
- package/src/services/zone.ts +8 -8
- package/src/storage/abstract.ts +58 -58
- package/src/storage/in-memory.ts +419 -419
- package/src/types.ts +82 -82
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* This module implements the commercetools product projection filter expression.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
ProductProjection,
|
|
7
|
+
ProductVariant,
|
|
8
|
+
} from '@commercetools/platform-sdk'
|
|
6
9
|
import { nestedLookup } from '../helpers.js'
|
|
7
10
|
import type { Writable } from '../types.js'
|
|
8
11
|
import { Lexer, Parser } from './parser.js'
|
|
@@ -10,48 +13,48 @@ import { Lexer, Parser } from './parser.js'
|
|
|
10
13
|
type MatchFunc = (target: any) => boolean
|
|
11
14
|
|
|
12
15
|
type ProductProjectionFilter = (
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
p: Writable<ProductProjection>,
|
|
17
|
+
markMatchingVariants: boolean
|
|
15
18
|
) => boolean
|
|
16
19
|
|
|
17
20
|
type TypeSymbol = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
type: 'Symbol'
|
|
22
|
+
kind: 'int' | 'string' | 'any'
|
|
23
|
+
value: any
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
type RangeExpressionSet = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
source: string
|
|
28
|
+
type: 'RangeExpression'
|
|
29
|
+
children?: RangeExpression[]
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
type FilterExpressionSet = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
source: string
|
|
34
|
+
type: 'FilterExpression'
|
|
35
|
+
children?: FilterExpression[]
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
type TermExpressionSet = {
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
source: string
|
|
40
|
+
type: 'TermExpression'
|
|
38
41
|
}
|
|
39
42
|
|
|
40
43
|
type ExpressionSet =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
| RangeExpressionSet
|
|
45
|
+
| FilterExpressionSet
|
|
46
|
+
| TermExpressionSet
|
|
44
47
|
|
|
45
48
|
export type RangeExpression = {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
type: 'RangeExpression'
|
|
50
|
+
start?: number
|
|
51
|
+
stop?: number
|
|
52
|
+
match: (obj: any) => boolean
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
export type FilterExpression = {
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
type: 'FilterExpression'
|
|
57
|
+
match: (obj: any) => boolean
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
/**
|
|
@@ -59,273 +62,273 @@ export type FilterExpression = {
|
|
|
59
62
|
* NOTE: The filter can alter the resources in-place (FIXME)
|
|
60
63
|
*/
|
|
61
64
|
export const parseFilterExpression = (
|
|
62
|
-
|
|
65
|
+
filter: string
|
|
63
66
|
): ProductProjectionFilter => {
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
const exprFunc = generateMatchFunc(filter)
|
|
68
|
+
const [source] = filter.split(':', 1)
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
if (source.startsWith('variants.')) {
|
|
71
|
+
return filterVariants(source, exprFunc)
|
|
72
|
+
}
|
|
73
|
+
return filterProduct(source, exprFunc)
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
const getLexer = (value: string) =>
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
77
|
+
new Lexer(value)
|
|
78
|
+
.token('MISSING', /missing(?![-_a-z0-9]+)/i)
|
|
79
|
+
.token('EXISTS', /exists(?![-_a-z0-9]+)/i)
|
|
80
|
+
.token('RANGE', /range(?![-_a-z0-9]+)/i)
|
|
81
|
+
.token('TO', /to(?![-_a-z0-9]+)/i)
|
|
82
|
+
.token('IDENTIFIER', /[-_.a-z]+/i)
|
|
83
|
+
|
|
84
|
+
.token('FLOAT', /\d+\.\d+/)
|
|
85
|
+
.token('INT', /\d+/)
|
|
86
|
+
.token('STRING', /"((?:\\.|[^"\\])*)"/)
|
|
87
|
+
.token('STRING', /'((?:\\.|[^'\\])*)'/)
|
|
88
|
+
|
|
89
|
+
.token('COMMA', ',')
|
|
90
|
+
.token('STAR', '*')
|
|
91
|
+
.token('(', '(')
|
|
92
|
+
.token(':', ':')
|
|
93
|
+
.token(')', ')')
|
|
94
|
+
.token('"', '"')
|
|
95
|
+
.token('WS', /\s+/, true) // skip
|
|
93
96
|
|
|
94
97
|
const parseFilter = (filter: string): ExpressionSet => {
|
|
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
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
98
|
+
const lexer = getLexer(filter)
|
|
99
|
+
const parser = new Parser(lexer)
|
|
100
|
+
.builder()
|
|
101
|
+
.nud('IDENTIFIER', 100, (t) => t.token.match)
|
|
102
|
+
.led(':', 100, ({ left, bp }) => {
|
|
103
|
+
const parsed: any = parser.parse({ terminals: [bp - 1] })
|
|
104
|
+
const expressions: RangeExpression[] | FilterExpression[] | TypeSymbol[] =
|
|
105
|
+
!Array.isArray(parsed) ? [parsed] : parsed
|
|
106
|
+
|
|
107
|
+
// Make sure we only have one type of expression (cannot mix)
|
|
108
|
+
const unique = new Set(expressions.map((expr) => expr.type))
|
|
109
|
+
if (unique.size > 1) {
|
|
110
|
+
throw new Error('Invalid expression')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Convert plain symbols to a filter expression. For example
|
|
114
|
+
// variants.attribute.foobar:4 where 4 is a Symbol should result
|
|
115
|
+
// in a comparison
|
|
116
|
+
if (expressions.some((expr) => expr.type == 'Symbol')) {
|
|
117
|
+
return {
|
|
118
|
+
source: left as string,
|
|
119
|
+
type: 'FilterExpression',
|
|
120
|
+
children: expressions.map((e): FilterExpression => {
|
|
121
|
+
if (e.type != 'Symbol') {
|
|
122
|
+
throw new Error('Invalid expression')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
type: 'FilterExpression',
|
|
127
|
+
match: (obj: any): boolean => obj === e.value,
|
|
128
|
+
}
|
|
129
|
+
}),
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
source: left,
|
|
135
|
+
type: expressions[0].type,
|
|
136
|
+
children: expressions,
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
.nud(
|
|
140
|
+
'STRING',
|
|
141
|
+
20,
|
|
142
|
+
(t) =>
|
|
143
|
+
({
|
|
144
|
+
type: 'Symbol',
|
|
145
|
+
kind: 'string',
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
value: t.token.groups[1],
|
|
148
|
+
}) as TypeSymbol
|
|
149
|
+
)
|
|
150
|
+
.nud(
|
|
151
|
+
'INT',
|
|
152
|
+
5,
|
|
153
|
+
(t) =>
|
|
154
|
+
({
|
|
155
|
+
type: 'Symbol',
|
|
156
|
+
kind: 'int',
|
|
157
|
+
value: parseInt(t.token.match, 10),
|
|
158
|
+
}) as TypeSymbol
|
|
159
|
+
)
|
|
160
|
+
.nud('STAR', 5, (_) => ({
|
|
161
|
+
type: 'Symbol',
|
|
162
|
+
kind: 'any',
|
|
163
|
+
value: null,
|
|
164
|
+
}))
|
|
165
|
+
.nud(
|
|
166
|
+
'EXISTS',
|
|
167
|
+
10,
|
|
168
|
+
({ bp }) =>
|
|
169
|
+
({
|
|
170
|
+
type: 'FilterExpression',
|
|
171
|
+
match: (obj: any): boolean => obj !== undefined,
|
|
172
|
+
}) as FilterExpression
|
|
173
|
+
)
|
|
174
|
+
.nud(
|
|
175
|
+
'MISSING',
|
|
176
|
+
10,
|
|
177
|
+
({ bp }) =>
|
|
178
|
+
({
|
|
179
|
+
type: 'FilterExpression',
|
|
180
|
+
match: (obj: any): boolean => obj === undefined,
|
|
181
|
+
}) as FilterExpression
|
|
182
|
+
)
|
|
183
|
+
.led('COMMA', 200, ({ left, token, bp }) => {
|
|
184
|
+
const expr: any = parser.parse({ terminals: [bp - 1] })
|
|
185
|
+
if (Array.isArray(expr)) {
|
|
186
|
+
return [left, ...expr]
|
|
187
|
+
} else {
|
|
188
|
+
return [left, expr]
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
.nud('(', 100, (t) => {
|
|
192
|
+
const expr: any = parser.parse({ terminals: [')'] })
|
|
193
|
+
lexer.expect(')')
|
|
194
|
+
return expr
|
|
195
|
+
})
|
|
196
|
+
.bp(')', 0)
|
|
197
|
+
.led('TO', 20, ({ left, bp }) => {
|
|
198
|
+
const expr: any = parser.parse({ terminals: [bp - 1] })
|
|
199
|
+
return {
|
|
200
|
+
start: left.value,
|
|
201
|
+
stop: expr.value,
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
.nud('RANGE', 20, ({ bp }) => {
|
|
205
|
+
let ranges: any = parser.parse()
|
|
206
|
+
|
|
207
|
+
// If multiple ranges are defined we receive an array of ranges. So let's
|
|
208
|
+
// make sure we always have an array
|
|
209
|
+
if (!Array.isArray(ranges)) {
|
|
210
|
+
ranges = [ranges]
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Return a list of functions which matches the ranges. These functions
|
|
214
|
+
// are processed as an OR clause
|
|
215
|
+
return ranges.map((range: any) => {
|
|
216
|
+
let func: (obj: any) => boolean
|
|
217
|
+
|
|
218
|
+
if (range.start !== null && range.stop !== null) {
|
|
219
|
+
func = (obj: any): boolean => obj >= range.start && obj <= range.stop
|
|
220
|
+
} else if (range.start === null && range.stop !== null) {
|
|
221
|
+
func = (obj: any): boolean => obj <= range.stop
|
|
222
|
+
} else if (range.start !== null && range.stop === null) {
|
|
223
|
+
func = (obj: any): boolean => obj >= range.start
|
|
224
|
+
} else {
|
|
225
|
+
func = (obj: any): boolean => true
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
type: 'RangeExpression',
|
|
230
|
+
start: range.start,
|
|
231
|
+
stop: range.stop,
|
|
232
|
+
match: func,
|
|
233
|
+
} as RangeExpression
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
.build()
|
|
237
|
+
|
|
238
|
+
return parser.parse()
|
|
236
239
|
}
|
|
237
240
|
|
|
238
241
|
const generateMatchFunc = (filter: string) => {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
242
|
+
const result = parseFilter(filter)
|
|
243
|
+
if (!result) {
|
|
244
|
+
// const lines = filter.split('\n')
|
|
245
|
+
// const column = lines[lines.length - 1].length
|
|
246
|
+
throw new Error(`Syntax error while parsing '${filter}'.`)
|
|
247
|
+
}
|
|
248
|
+
if (result.type == 'TermExpression') {
|
|
249
|
+
throw new Error(`Syntax error while parsing '${filter}'.`)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return (obj: any) => {
|
|
253
|
+
if (!result.children) return false
|
|
254
|
+
return result.children.some((c) => c.match(obj))
|
|
255
|
+
}
|
|
253
256
|
}
|
|
254
257
|
|
|
255
258
|
export const generateFacetFunc = (filter: string): ExpressionSet => {
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
if (!filter.includes(':')) {
|
|
260
|
+
return {
|
|
261
|
+
source: filter,
|
|
262
|
+
type: 'TermExpression',
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return parseFilter(filter)
|
|
263
266
|
}
|
|
264
267
|
|
|
265
268
|
const filterProduct =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
(source: string, exprFunc: MatchFunc): ProductProjectionFilter =>
|
|
270
|
+
(p: ProductProjection, markMatchingVariants: boolean): boolean => {
|
|
271
|
+
const value = nestedLookup(p, source)
|
|
272
|
+
return exprFunc(value)
|
|
273
|
+
}
|
|
271
274
|
|
|
272
275
|
const filterVariants =
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
276
|
+
(source: string, exprFunc: MatchFunc): ProductProjectionFilter =>
|
|
277
|
+
(p: ProductProjection, markMatchingVariants: boolean): boolean => {
|
|
278
|
+
const [, ...paths] = source.split('.')
|
|
279
|
+
const path = paths.join('.')
|
|
280
|
+
|
|
281
|
+
const variants = getVariants(p) as Writable<ProductVariant>[]
|
|
282
|
+
for (const variant of variants) {
|
|
283
|
+
const value = resolveVariantValue(variant, path)
|
|
284
|
+
|
|
285
|
+
if (exprFunc(value)) {
|
|
286
|
+
// If markMatchingVariants parameter is true those ProductVariants that
|
|
287
|
+
// match the search query have the additional field isMatchingVariant
|
|
288
|
+
// set to true. For the other variants in the same product projection
|
|
289
|
+
// this field is set to false.
|
|
290
|
+
if (markMatchingVariants) {
|
|
291
|
+
variants.forEach((v) => (v.isMatchingVariant = false))
|
|
292
|
+
variant.isMatchingVariant = true
|
|
293
|
+
}
|
|
294
|
+
return true
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return false
|
|
299
|
+
}
|
|
297
300
|
|
|
298
301
|
export const resolveVariantValue = (obj: ProductVariant, path: string): any => {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
302
|
+
if (path === undefined) {
|
|
303
|
+
return obj
|
|
304
|
+
}
|
|
305
|
+
if (path.startsWith('variants.')) {
|
|
306
|
+
path = path.substring(path.indexOf('.') + 1)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (path.startsWith('attributes.')) {
|
|
310
|
+
const [, attrName, ...rest] = path.split('.')
|
|
311
|
+
if (!obj.attributes) {
|
|
312
|
+
return undefined
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
for (const attr of obj.attributes) {
|
|
316
|
+
if (attr.name === attrName) {
|
|
317
|
+
return nestedLookup(attr.value, rest.join('.'))
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (path === 'price.centAmount') {
|
|
323
|
+
return obj.prices && obj.prices.length > 0
|
|
324
|
+
? obj.prices[0].value.centAmount
|
|
325
|
+
: undefined
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return nestedLookup(obj, path)
|
|
326
329
|
}
|
|
327
330
|
|
|
328
331
|
export const getVariants = (p: ProductProjection): ProductVariant[] => [
|
|
329
|
-
|
|
330
|
-
|
|
332
|
+
p.masterVariant,
|
|
333
|
+
...(p.variants ?? []),
|
|
331
334
|
]
|
package/src/lib/proxy.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export const copyHeaders = (headers: Record<string, string>) => {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
const validHeaders = ['accept', 'host', 'authorization']
|
|
3
|
+
const result: Record<string, string> = {}
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
6
|
+
if (validHeaders.includes(key.toLowerCase())) {
|
|
7
|
+
result[key] = value
|
|
8
|
+
}
|
|
9
|
+
})
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
return result
|
|
12
12
|
}
|
package/src/oauth/errors.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export interface InvalidClientError {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
readonly code: 'invalid_client'
|
|
3
|
+
readonly message: string
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
export interface UnsupportedGrantType {
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
readonly code: 'unsupported_grant_type'
|
|
8
|
+
readonly message: string
|
|
9
9
|
}
|
package/src/oauth/helpers.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Request } from 'express'
|
|
2
2
|
|
|
3
3
|
export const getBearerToken = (request: Request): string | undefined => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
const authHeader = request.header('Authorization')
|
|
5
|
+
const match = authHeader?.match(/^Bearer\s(?<token>[^\s]+)$/)
|
|
6
|
+
if (match) {
|
|
7
|
+
return match.groups?.token
|
|
8
|
+
}
|
|
9
|
+
return undefined
|
|
10
10
|
}
|