@labdigital/commercetools-mock 0.9.0 → 0.10.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 +8 -0
- package/dist/index.d.ts +18 -17
- package/dist/index.global.js +1751 -1664
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +1773 -1684
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1966 -1877
- package/dist/index.mjs.map +1 -1
- package/package.json +28 -20
- package/src/constants.ts +4 -2
- package/src/ctMock.ts +19 -84
- package/src/helpers.ts +9 -10
- package/src/index.test.ts +1 -1
- package/src/lib/haversine.ts +2 -2
- package/src/lib/masking.ts +3 -1
- package/src/lib/predicateParser.test.ts +16 -0
- package/src/lib/predicateParser.ts +94 -86
- package/src/lib/projectionSearchFilter.test.ts +28 -36
- package/src/lib/projectionSearchFilter.ts +86 -102
- package/src/oauth/store.ts +3 -3
- package/src/priceSelector.test.ts +18 -35
- package/src/priceSelector.ts +6 -9
- package/src/product-projection-search.ts +51 -57
- package/src/repositories/abstract.ts +85 -41
- package/src/repositories/cart-discount.ts +1 -1
- package/src/repositories/cart.ts +36 -31
- package/src/repositories/category.ts +17 -19
- package/src/repositories/channel.ts +1 -1
- package/src/repositories/custom-object.ts +35 -22
- package/src/repositories/customer-group.ts +1 -1
- package/src/repositories/customer.ts +39 -1
- package/src/repositories/discount-code.ts +1 -1
- package/src/repositories/errors.ts +9 -11
- package/src/repositories/extension.ts +13 -11
- package/src/repositories/helpers.ts +8 -13
- package/src/repositories/index.ts +59 -0
- package/src/repositories/inventory-entry.ts +1 -1
- package/src/repositories/order.ts +6 -6
- package/src/repositories/payment.ts +3 -3
- package/src/repositories/product-discount.ts +1 -1
- package/src/repositories/product-projection.ts +1 -0
- package/src/repositories/product-type.ts +29 -34
- package/src/repositories/product.ts +124 -80
- package/src/repositories/project.ts +10 -27
- package/src/repositories/shipping-method.ts +15 -17
- package/src/repositories/shopping-list.ts +2 -2
- package/src/repositories/state.ts +9 -9
- package/src/repositories/store.ts +2 -2
- package/src/repositories/subscription.ts +1 -1
- package/src/repositories/tax-category.ts +4 -4
- package/src/repositories/type.ts +12 -14
- package/src/repositories/zone.ts +5 -6
- package/src/server.ts +5 -0
- package/src/services/abstract.ts +44 -11
- package/src/services/cart-discount.ts +2 -3
- package/src/services/cart.test.ts +8 -10
- package/src/services/cart.ts +8 -11
- package/src/services/category.test.ts +1 -2
- package/src/services/category.ts +2 -3
- package/src/services/channel.ts +2 -3
- package/src/services/custom-object.test.ts +5 -5
- package/src/services/custom-object.ts +2 -3
- package/src/services/customer-group.ts +2 -3
- package/src/services/customer.test.ts +136 -0
- package/src/services/customer.ts +2 -3
- package/src/services/discount-code.ts +2 -3
- package/src/services/extension.ts +2 -3
- package/src/services/index.ts +74 -0
- package/src/services/inventory-entry.test.ts +8 -12
- package/src/services/inventory-entry.ts +2 -3
- package/src/services/my-cart.ts +3 -4
- package/src/services/my-customer.ts +2 -3
- package/src/services/my-order.ts +3 -4
- package/src/services/my-payment.ts +2 -3
- package/src/services/order.test.ts +4 -6
- package/src/services/order.ts +2 -3
- package/src/services/payment.ts +2 -3
- package/src/services/product-discount.ts +2 -3
- package/src/services/product-projection.test.ts +76 -8
- package/src/services/product-projection.ts +2 -3
- package/src/services/product-type.ts +2 -3
- package/src/services/product.test.ts +199 -89
- package/src/services/product.ts +2 -3
- package/src/services/project.ts +3 -3
- package/src/services/shipping-method.ts +2 -3
- package/src/services/shopping-list.ts +2 -3
- package/src/services/state.ts +2 -3
- package/src/services/store.test.ts +11 -2
- package/src/services/store.ts +2 -3
- package/src/services/subscription.ts +2 -3
- package/src/services/tax-category.ts +2 -3
- package/src/services/type.ts +2 -3
- package/src/services/zone.ts +2 -3
- package/src/storage.ts +23 -30
- package/src/types.ts +46 -6
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* This module implements the commercetools product projection filter expression.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { ProductProjection, ProductVariant } from '@commercetools/platform-sdk'
|
|
6
6
|
import perplex from 'perplex'
|
|
7
7
|
import Parser from 'pratt'
|
|
8
8
|
import { nestedLookup } from '../helpers'
|
|
@@ -10,12 +10,12 @@ import { Writable } from '../types'
|
|
|
10
10
|
|
|
11
11
|
type MatchFunc = (target: any) => boolean
|
|
12
12
|
|
|
13
|
-
type
|
|
14
|
-
p: Writable<
|
|
13
|
+
type ProductProjectionFilter = (
|
|
14
|
+
p: Writable<ProductProjection>,
|
|
15
15
|
markMatchingVariants: boolean
|
|
16
16
|
) => boolean
|
|
17
17
|
|
|
18
|
-
type
|
|
18
|
+
type TypeSymbol = {
|
|
19
19
|
type: 'Symbol'
|
|
20
20
|
kind: 'int' | 'string' | 'any'
|
|
21
21
|
value: any
|
|
@@ -38,7 +38,10 @@ type TermExpressionSet = {
|
|
|
38
38
|
type: 'TermExpression'
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
type ExpressionSet =
|
|
41
|
+
type ExpressionSet =
|
|
42
|
+
| RangeExpressionSet
|
|
43
|
+
| FilterExpressionSet
|
|
44
|
+
| TermExpressionSet
|
|
42
45
|
|
|
43
46
|
export type RangeExpression = {
|
|
44
47
|
type: 'RangeExpression'
|
|
@@ -53,29 +56,28 @@ export type FilterExpression = {
|
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
/**
|
|
56
|
-
* Returns a function (
|
|
59
|
+
* Returns a function (ProductProjectionFilter).
|
|
57
60
|
* NOTE: The filter can alter the resources in-place (FIXME)
|
|
58
61
|
*/
|
|
59
62
|
export const parseFilterExpression = (
|
|
60
|
-
filter: string
|
|
61
|
-
|
|
62
|
-
): ProductFilter => {
|
|
63
|
+
filter: string
|
|
64
|
+
): ProductProjectionFilter => {
|
|
63
65
|
const exprFunc = generateMatchFunc(filter)
|
|
64
66
|
const [source] = filter.split(':', 1)
|
|
65
67
|
|
|
66
68
|
if (source.startsWith('variants.')) {
|
|
67
|
-
return filterVariants(source,
|
|
69
|
+
return filterVariants(source, exprFunc)
|
|
68
70
|
}
|
|
69
71
|
return filterProduct(source, exprFunc)
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
const getLexer = (value: string) =>
|
|
73
|
-
|
|
74
|
+
const getLexer = (value: string) =>
|
|
75
|
+
new perplex(value)
|
|
74
76
|
.token('MISSING', /missing(?![-_a-z0-9]+)/i)
|
|
75
77
|
.token('EXISTS', /exists(?![-_a-z0-9]+)/i)
|
|
76
78
|
.token('RANGE', /range(?![-_a-z0-9]+)/i)
|
|
77
79
|
.token('TO', /to(?![-_a-z0-9]+)/i)
|
|
78
|
-
.token('IDENTIFIER', /[-_
|
|
80
|
+
.token('IDENTIFIER', /[-_.a-z]+/i)
|
|
79
81
|
|
|
80
82
|
.token('FLOAT', /\d+\.\d+/)
|
|
81
83
|
.token('INT', /\d+/)
|
|
@@ -89,22 +91,18 @@ const getLexer = (value: string) => {
|
|
|
89
91
|
.token(')', ')')
|
|
90
92
|
.token('"', '"')
|
|
91
93
|
.token('WS', /\s+/, true) // skip
|
|
92
|
-
}
|
|
93
94
|
|
|
94
95
|
const parseFilter = (filter: string): ExpressionSet => {
|
|
95
96
|
const lexer = getLexer(filter)
|
|
96
97
|
const parser = new Parser(lexer)
|
|
97
98
|
.builder()
|
|
98
|
-
.nud('IDENTIFIER', 100, t =>
|
|
99
|
-
return t.token.match
|
|
100
|
-
})
|
|
99
|
+
.nud('IDENTIFIER', 100, (t) => t.token.match)
|
|
101
100
|
.led(':', 100, ({ left, bp }) => {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
expressions = !Array.isArray(parsed) ? [parsed] : parsed
|
|
101
|
+
const parsed: any = parser.parse({ terminals: [bp - 1] })
|
|
102
|
+
const expressions: RangeExpression[] | FilterExpression[] | TypeSymbol[] = !Array.isArray(parsed) ? [parsed] : parsed
|
|
105
103
|
|
|
106
104
|
// Make sure we only have one type of expression (cannot mix)
|
|
107
|
-
const unique = new Set(expressions.map(expr => expr.type))
|
|
105
|
+
const unique = new Set(expressions.map((expr) => expr.type))
|
|
108
106
|
if (unique.size > 1) {
|
|
109
107
|
throw new Error('Invalid expression')
|
|
110
108
|
}
|
|
@@ -112,7 +110,7 @@ const parseFilter = (filter: string): ExpressionSet => {
|
|
|
112
110
|
// Convert plain symbols to a filter expression. For example
|
|
113
111
|
// variants.attribute.foobar:4 where 4 is a Symbol should result
|
|
114
112
|
// in a comparison
|
|
115
|
-
if (expressions.some(expr => expr.type == 'Symbol')) {
|
|
113
|
+
if (expressions.some((expr) => expr.type == 'Symbol')) {
|
|
116
114
|
return {
|
|
117
115
|
source: left as string,
|
|
118
116
|
type: 'FilterExpression',
|
|
@@ -123,11 +121,9 @@ const parseFilter = (filter: string): ExpressionSet => {
|
|
|
123
121
|
|
|
124
122
|
return {
|
|
125
123
|
type: 'FilterExpression',
|
|
126
|
-
match: (obj: any): boolean =>
|
|
127
|
-
return obj === e.value
|
|
128
|
-
},
|
|
124
|
+
match: (obj: any): boolean => obj === e.value,
|
|
129
125
|
}
|
|
130
|
-
})
|
|
126
|
+
}),
|
|
131
127
|
}
|
|
132
128
|
}
|
|
133
129
|
|
|
@@ -137,44 +133,50 @@ const parseFilter = (filter: string): ExpressionSet => {
|
|
|
137
133
|
children: expressions,
|
|
138
134
|
}
|
|
139
135
|
})
|
|
140
|
-
.nud(
|
|
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
|
-
|
|
136
|
+
.nud(
|
|
137
|
+
'STRING',
|
|
138
|
+
20,
|
|
139
|
+
(t) =>
|
|
140
|
+
({
|
|
141
|
+
type: 'Symbol',
|
|
142
|
+
kind: 'string',
|
|
143
|
+
// @ts-ignore
|
|
144
|
+
value: t.token.groups[1],
|
|
145
|
+
} as TypeSymbol)
|
|
146
|
+
)
|
|
147
|
+
.nud(
|
|
148
|
+
'INT',
|
|
149
|
+
5,
|
|
150
|
+
(t) =>
|
|
151
|
+
({
|
|
152
|
+
type: 'Symbol',
|
|
153
|
+
kind: 'int',
|
|
154
|
+
value: parseInt(t.token.match, 10),
|
|
155
|
+
} as TypeSymbol)
|
|
156
|
+
)
|
|
157
|
+
.nud('STAR', 5, (_) => ({
|
|
158
|
+
type: 'Symbol',
|
|
159
|
+
kind: 'any',
|
|
160
|
+
value: null,
|
|
161
|
+
}))
|
|
162
|
+
.nud(
|
|
163
|
+
'EXISTS',
|
|
164
|
+
10,
|
|
165
|
+
({ bp }) =>
|
|
166
|
+
({
|
|
167
|
+
type: 'FilterExpression',
|
|
168
|
+
match: (obj: any): boolean => obj !== undefined,
|
|
169
|
+
} as FilterExpression)
|
|
170
|
+
)
|
|
171
|
+
.nud(
|
|
172
|
+
'MISSING',
|
|
173
|
+
10,
|
|
174
|
+
({ bp }) =>
|
|
175
|
+
({
|
|
176
|
+
type: 'FilterExpression',
|
|
177
|
+
match: (obj: any): boolean => obj === undefined,
|
|
178
|
+
} as FilterExpression)
|
|
179
|
+
)
|
|
178
180
|
.led('COMMA', 200, ({ left, token, bp }) => {
|
|
179
181
|
const expr: any = parser.parse({ terminals: [bp - 1] })
|
|
180
182
|
if (Array.isArray(expr)) {
|
|
@@ -183,7 +185,7 @@ const parseFilter = (filter: string): ExpressionSet => {
|
|
|
183
185
|
return [left, expr]
|
|
184
186
|
}
|
|
185
187
|
})
|
|
186
|
-
.nud('(', 100, t => {
|
|
188
|
+
.nud('(', 100, (t) => {
|
|
187
189
|
const expr: any = parser.parse({ terminals: [')'] })
|
|
188
190
|
lexer.expect(')')
|
|
189
191
|
return expr
|
|
@@ -211,21 +213,13 @@ const parseFilter = (filter: string): ExpressionSet => {
|
|
|
211
213
|
let func = undefined
|
|
212
214
|
|
|
213
215
|
if (range.start !== null && range.stop !== null) {
|
|
214
|
-
func = (obj: any): boolean =>
|
|
215
|
-
return obj >= range.start && obj <= range.stop
|
|
216
|
-
}
|
|
216
|
+
func = (obj: any): boolean => obj >= range.start && obj <= range.stop
|
|
217
217
|
} else if (range.start === null && range.stop !== null) {
|
|
218
|
-
func = (obj: any): boolean =>
|
|
219
|
-
return obj <= range.stop
|
|
220
|
-
}
|
|
218
|
+
func = (obj: any): boolean => obj <= range.stop
|
|
221
219
|
} else if (range.start !== null && range.stop === null) {
|
|
222
|
-
func = (obj: any): boolean =>
|
|
223
|
-
return obj >= range.start
|
|
224
|
-
}
|
|
220
|
+
func = (obj: any): boolean => obj >= range.start
|
|
225
221
|
} else {
|
|
226
|
-
func = (obj: any): boolean =>
|
|
227
|
-
return true
|
|
228
|
-
}
|
|
222
|
+
func = (obj: any): boolean => true
|
|
229
223
|
}
|
|
230
224
|
|
|
231
225
|
return {
|
|
@@ -244,8 +238,8 @@ const parseFilter = (filter: string): ExpressionSet => {
|
|
|
244
238
|
const generateMatchFunc = (filter: string) => {
|
|
245
239
|
const result = parseFilter(filter)
|
|
246
240
|
if (!result) {
|
|
247
|
-
const lines = filter.split('\n')
|
|
248
|
-
const column = lines[lines.length - 1].length
|
|
241
|
+
// const lines = filter.split('\n')
|
|
242
|
+
// const column = lines[lines.length - 1].length
|
|
249
243
|
throw new Error(`Syntax error while parsing '${filter}'.`)
|
|
250
244
|
}
|
|
251
245
|
if (result.type == 'TermExpression') {
|
|
@@ -254,7 +248,7 @@ const generateMatchFunc = (filter: string) => {
|
|
|
254
248
|
|
|
255
249
|
return (obj: any) => {
|
|
256
250
|
if (!result.children) return false
|
|
257
|
-
return result.children.some(c => c.match(obj))
|
|
251
|
+
return result.children.some((c) => c.match(obj))
|
|
258
252
|
}
|
|
259
253
|
}
|
|
260
254
|
|
|
@@ -268,23 +262,20 @@ export const generateFacetFunc = (filter: string): ExpressionSet => {
|
|
|
268
262
|
return parseFilter(filter)
|
|
269
263
|
}
|
|
270
264
|
|
|
271
|
-
const filterProduct =
|
|
272
|
-
|
|
265
|
+
const filterProduct =
|
|
266
|
+
(source: string, exprFunc: MatchFunc): ProductProjectionFilter =>
|
|
267
|
+
(p: ProductProjection, markMatchingVariants: boolean): boolean => {
|
|
273
268
|
const value = nestedLookup(p, source)
|
|
274
269
|
return exprFunc(value)
|
|
275
270
|
}
|
|
276
|
-
}
|
|
277
271
|
|
|
278
|
-
const filterVariants =
|
|
279
|
-
source: string,
|
|
280
|
-
|
|
281
|
-
exprFunc: MatchFunc
|
|
282
|
-
): ProductFilter => {
|
|
283
|
-
return (p: Product, markMatchingVariants: boolean): boolean => {
|
|
272
|
+
const filterVariants =
|
|
273
|
+
(source: string, exprFunc: MatchFunc): ProductProjectionFilter =>
|
|
274
|
+
(p: ProductProjection, markMatchingVariants: boolean): boolean => {
|
|
284
275
|
const [, ...paths] = source.split('.')
|
|
285
276
|
const path = paths.join('.')
|
|
286
277
|
|
|
287
|
-
const variants = getVariants(p
|
|
278
|
+
const variants = getVariants(p) as Writable<ProductVariant>[]
|
|
288
279
|
for (const variant of variants) {
|
|
289
280
|
const value = resolveVariantValue(variant, path)
|
|
290
281
|
|
|
@@ -294,7 +285,7 @@ const filterVariants = (
|
|
|
294
285
|
// set to true. For the other variants in the same product projection
|
|
295
286
|
// this field is set to false.
|
|
296
287
|
if (markMatchingVariants) {
|
|
297
|
-
variants.forEach(v => (v.isMatchingVariant = false))
|
|
288
|
+
variants.forEach((v) => (v.isMatchingVariant = false))
|
|
298
289
|
variant.isMatchingVariant = true
|
|
299
290
|
}
|
|
300
291
|
return true
|
|
@@ -303,7 +294,6 @@ const filterVariants = (
|
|
|
303
294
|
|
|
304
295
|
return false
|
|
305
296
|
}
|
|
306
|
-
}
|
|
307
297
|
|
|
308
298
|
export const resolveVariantValue = (obj: ProductVariant, path: string): any => {
|
|
309
299
|
if (path === undefined) {
|
|
@@ -335,13 +325,7 @@ export const resolveVariantValue = (obj: ProductVariant, path: string): any => {
|
|
|
335
325
|
return nestedLookup(obj, path)
|
|
336
326
|
}
|
|
337
327
|
|
|
338
|
-
export const getVariants = (p:
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
: p.masterData.current?.masterVariant,
|
|
343
|
-
...(staged
|
|
344
|
-
? p.masterData.staged?.variants
|
|
345
|
-
: p.masterData.current?.variants),
|
|
346
|
-
]
|
|
347
|
-
}
|
|
328
|
+
export const getVariants = (p: ProductProjection): ProductVariant[] => [
|
|
329
|
+
p.masterVariant,
|
|
330
|
+
...(p.variants ?? []),
|
|
331
|
+
]
|
package/src/oauth/store.ts
CHANGED
|
@@ -9,9 +9,9 @@ type Token = {
|
|
|
9
9
|
|
|
10
10
|
export class OAuth2Store {
|
|
11
11
|
tokens: Token[] = []
|
|
12
|
-
validate
|
|
12
|
+
validate = true
|
|
13
13
|
|
|
14
|
-
constructor(validate
|
|
14
|
+
constructor(validate = true) {
|
|
15
15
|
this.validate = validate
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -29,7 +29,7 @@ export class OAuth2Store {
|
|
|
29
29
|
validateToken(token: string) {
|
|
30
30
|
if (!this.validate) return true
|
|
31
31
|
|
|
32
|
-
const foundToken = this.tokens.find(t => t.access_token === token)
|
|
32
|
+
const foundToken = this.tokens.find((t) => t.access_token === token)
|
|
33
33
|
if (foundToken) {
|
|
34
34
|
return true
|
|
35
35
|
}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ProductProjection,
|
|
3
|
+
} from '@commercetools/platform-sdk'
|
|
2
4
|
import { applyPriceSelector } from './priceSelector'
|
|
3
5
|
|
|
4
6
|
describe('priceSelector', () => {
|
|
5
|
-
let product:
|
|
7
|
+
let product: ProductProjection
|
|
6
8
|
|
|
7
9
|
beforeEach(() => {
|
|
8
|
-
|
|
10
|
+
product = {
|
|
11
|
+
id: '7401d82f-1378-47ba-996a-85beeb87ac87',
|
|
12
|
+
version: 2,
|
|
13
|
+
createdAt: '2022-07-22T10:02:40.851Z',
|
|
14
|
+
lastModifiedAt: '2022-07-22T10:02:44.427Z',
|
|
15
|
+
productType: {
|
|
16
|
+
typeId: 'product-type',
|
|
17
|
+
id: 'b9b4b426-938b-4ccb-9f36-c6f933e8446e',
|
|
18
|
+
},
|
|
9
19
|
name: {
|
|
10
20
|
'nl-NL': 'test',
|
|
11
21
|
},
|
|
@@ -48,49 +58,22 @@ describe('priceSelector', () => {
|
|
|
48
58
|
],
|
|
49
59
|
},
|
|
50
60
|
}
|
|
51
|
-
|
|
52
|
-
product = {
|
|
53
|
-
id: '7401d82f-1378-47ba-996a-85beeb87ac87',
|
|
54
|
-
version: 2,
|
|
55
|
-
createdAt: '2022-07-22T10:02:40.851Z',
|
|
56
|
-
lastModifiedAt: '2022-07-22T10:02:44.427Z',
|
|
57
|
-
productType: {
|
|
58
|
-
typeId: 'product-type',
|
|
59
|
-
id: 'b9b4b426-938b-4ccb-9f36-c6f933e8446e',
|
|
60
|
-
},
|
|
61
|
-
masterData: {
|
|
62
|
-
current: productData,
|
|
63
|
-
staged: productData,
|
|
64
|
-
published: true,
|
|
65
|
-
hasStagedChanges: false,
|
|
66
|
-
},
|
|
67
|
-
}
|
|
68
61
|
})
|
|
69
62
|
|
|
70
63
|
test('currency (match)', async () => {
|
|
71
64
|
applyPriceSelector([product], { currency: 'EUR' })
|
|
72
65
|
|
|
73
66
|
expect(product).toMatchObject({
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
sku: 'MYSKU',
|
|
78
|
-
scopedPrice: { value: { centAmount: 1789 } },
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
staged: {
|
|
82
|
-
masterVariant: {
|
|
83
|
-
sku: 'MYSKU',
|
|
84
|
-
scopedPrice: { value: { centAmount: 1789 } },
|
|
85
|
-
},
|
|
86
|
-
},
|
|
67
|
+
masterVariant: {
|
|
68
|
+
sku: 'MYSKU',
|
|
69
|
+
scopedPrice: { value: { centAmount: 1789 } },
|
|
87
70
|
},
|
|
88
71
|
})
|
|
89
72
|
})
|
|
90
73
|
|
|
91
74
|
test('currency, country (no match)', async () => {
|
|
92
75
|
applyPriceSelector([product], { currency: 'EUR', country: 'US' })
|
|
93
|
-
expect(product.
|
|
94
|
-
expect(product.
|
|
76
|
+
expect(product.masterVariant.scopedPrice).toBeUndefined()
|
|
77
|
+
expect(product.masterVariant.scopedPrice).toBeUndefined()
|
|
95
78
|
})
|
|
96
79
|
})
|
package/src/priceSelector.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InvalidInputError,
|
|
3
3
|
Price,
|
|
4
|
-
|
|
4
|
+
ProductProjection,
|
|
5
5
|
ProductVariant,
|
|
6
6
|
} from '@commercetools/platform-sdk'
|
|
7
7
|
import { CommercetoolsError } from './exceptions'
|
|
@@ -20,23 +20,20 @@ export type PriceSelector = {
|
|
|
20
20
|
* the scopedPrice attribute
|
|
21
21
|
*/
|
|
22
22
|
export const applyPriceSelector = (
|
|
23
|
-
products:
|
|
23
|
+
products: ProductProjection[],
|
|
24
24
|
selector: PriceSelector
|
|
25
25
|
) => {
|
|
26
26
|
validatePriceSelector(selector)
|
|
27
27
|
|
|
28
28
|
for (const product of products) {
|
|
29
29
|
const variants: Writable<ProductVariant>[] = [
|
|
30
|
-
product.
|
|
31
|
-
...(product.
|
|
32
|
-
|
|
33
|
-
product.masterData.current?.masterVariant,
|
|
34
|
-
...(product.masterData.current?.variants || []),
|
|
35
|
-
].filter(x => x != undefined)
|
|
30
|
+
product.masterVariant,
|
|
31
|
+
...(product.variants ?? []),
|
|
32
|
+
].filter((x) => x != undefined)
|
|
36
33
|
|
|
37
34
|
for (const variant of variants) {
|
|
38
35
|
const scopedPrices =
|
|
39
|
-
variant.prices?.filter(p => priceSelectorFilter(p, selector)) ?? []
|
|
36
|
+
variant.prices?.filter((p) => priceSelectorFilter(p, selector)) ?? []
|
|
40
37
|
|
|
41
38
|
if (scopedPrices.length > 0) {
|
|
42
39
|
const price = scopedPrices[0]
|