@labdigital/commercetools-mock 2.46.0 → 2.47.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.
Files changed (79) hide show
  1. package/dist/index.cjs +568 -241
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +782 -58
  4. package/dist/index.d.ts +782 -58
  5. package/dist/index.js +556 -229
  6. package/dist/index.js.map +1 -1
  7. package/package.json +41 -48
  8. package/src/ctMock.ts +11 -13
  9. package/src/index.test.ts +5 -5
  10. package/src/lib/predicateParser.test.ts +62 -62
  11. package/src/lib/predicateParser.ts +32 -42
  12. package/src/lib/productSearchFilter.test.ts +18 -0
  13. package/src/lib/productSearchFilter.ts +7 -0
  14. package/src/lib/projectionSearchFilter.test.ts +17 -17
  15. package/src/lib/projectionSearchFilter.ts +2 -3
  16. package/src/oauth/server.test.ts +1 -1
  17. package/src/oauth/server.ts +11 -11
  18. package/src/priceSelector.ts +1 -1
  19. package/src/product-projection-search.ts +18 -19
  20. package/src/repositories/business-unit.ts +17 -16
  21. package/src/repositories/cart/actions.ts +32 -32
  22. package/src/repositories/cart/helpers.ts +1 -1
  23. package/src/repositories/cart/index.ts +8 -8
  24. package/src/repositories/cart-discount/actions.ts +1 -4
  25. package/src/repositories/category/actions.ts +2 -6
  26. package/src/repositories/custom-object.ts +20 -21
  27. package/src/repositories/customer/actions.ts +4 -4
  28. package/src/repositories/errors.ts +1 -1
  29. package/src/repositories/extension.ts +2 -1
  30. package/src/repositories/helpers.ts +27 -27
  31. package/src/repositories/index.ts +17 -17
  32. package/src/repositories/my-customer.ts +1 -1
  33. package/src/repositories/my-order.ts +2 -2
  34. package/src/repositories/order/index.ts +1 -1
  35. package/src/repositories/product/actions.ts +1 -1
  36. package/src/repositories/quote/actions.ts +83 -0
  37. package/src/repositories/quote/index.ts +54 -0
  38. package/src/repositories/quote-request/actions.ts +84 -0
  39. package/src/repositories/quote-request/index.test.ts +167 -0
  40. package/src/repositories/quote-request/index.ts +67 -0
  41. package/src/repositories/quote-staged/actions.ts +84 -0
  42. package/src/repositories/quote-staged/index.ts +47 -0
  43. package/src/repositories/review.ts +4 -4
  44. package/src/repositories/shipping-method/actions.ts +17 -17
  45. package/src/repositories/shipping-method/index.ts +6 -6
  46. package/src/repositories/shopping-list/actions.ts +1 -1
  47. package/src/repositories/shopping-list/index.ts +9 -1
  48. package/src/repositories/subscription.ts +2 -4
  49. package/src/server.ts +3 -2
  50. package/src/services/abstract.ts +7 -7
  51. package/src/services/as-associate-order.test.ts +1 -1
  52. package/src/services/cart-discount.test.ts +1 -1
  53. package/src/services/cart.test.ts +15 -15
  54. package/src/services/category.test.ts +1 -1
  55. package/src/services/customer.test.ts +4 -4
  56. package/src/services/customer.ts +1 -1
  57. package/src/services/index.ts +20 -14
  58. package/src/services/inventory-entry.test.ts +5 -5
  59. package/src/services/my-cart.test.ts +2 -2
  60. package/src/services/my-customer.test.ts +2 -2
  61. package/src/services/order.test.ts +8 -8
  62. package/src/services/product-projection.test.ts +5 -5
  63. package/src/services/product-projection.ts +12 -14
  64. package/src/services/product.test.ts +1 -1
  65. package/src/services/quote-request.test.ts +59 -0
  66. package/src/services/quote-request.ts +16 -0
  67. package/src/services/quote-staged.ts +16 -0
  68. package/src/services/quote.ts +16 -0
  69. package/src/services/standalone-price.test.ts +4 -4
  70. package/src/services/state.test.ts +1 -1
  71. package/src/services/store.test.ts +2 -2
  72. package/src/services/tax-category.test.ts +1 -1
  73. package/src/shipping.ts +3 -3
  74. package/src/storage/in-memory.ts +55 -63
  75. package/src/testing/customer.ts +1 -1
  76. package/src/types.ts +51 -31
  77. package/src/repositories/quote-request.ts +0 -17
  78. package/src/repositories/quote.ts +0 -14
  79. package/src/repositories/staged-quote.ts +0 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@labdigital/commercetools-mock",
3
- "version": "2.46.0",
3
+ "version": "2.47.0",
4
4
  "license": "MIT",
5
5
  "author": "Michael van Tellingen",
6
6
  "type": "module",
@@ -19,54 +19,46 @@
19
19
  "src"
20
20
  ],
21
21
  "dependencies": {
22
- "basic-auth": "^2.0.1",
23
- "body-parser": "^1.20.2",
22
+ "@biomejs/biome": "^1.9.4",
23
+ "basic-auth": "2.0.1",
24
+ "body-parser": "1.20.2",
24
25
  "decimal.js": "10.4.3",
25
- "deep-equal": "^2.2.3",
26
- "express": "^4.21.1",
27
- "light-my-request": "^5.11.1",
28
- "lodash.isequal": "^4.5.0",
29
- "morgan": "^1.10.0",
30
- "msw": "^2.5.0",
31
- "uuid": "^9.0.1",
32
- "zod": "^3.22.4",
33
- "zod-validation-error": "^3.0.2"
26
+ "deep-equal": "2.2.3",
27
+ "express": "4.21.1",
28
+ "light-my-request": "5.11.1",
29
+ "lodash.isequal": "4.5.0",
30
+ "morgan": "1.10.0",
31
+ "msw": "2.5.0",
32
+ "uuid": "9.0.1",
33
+ "zod": "3.22.4",
34
+ "zod-validation-error": "3.0.2"
34
35
  },
35
36
  "devDependencies": {
36
- "@changesets/changelog-github": "^0.5.0",
37
- "@changesets/cli": "^2.27.1",
38
- "@commercetools/platform-sdk": "7.17.0",
39
- "@stylistic/eslint-plugin": "^1.6.2",
40
- "@types/basic-auth": "^1.1.8",
41
- "@types/body-parser": "^1.19.5",
42
- "@types/deep-equal": "^1.0.4",
43
- "@types/express": "^4.17.21",
44
- "@types/express-serve-static-core": "^4.17.43",
45
- "@types/lodash.isequal": "^4.5.8",
46
- "@types/morgan": "^1.9.9",
47
- "@types/node": "^20.16.14",
48
- "@types/qs": "^6.9.11",
49
- "@types/supertest": "^6.0.2",
50
- "@types/uuid": "^9.0.8",
51
- "@typescript-eslint/eslint-plugin": "^7.0.2",
52
- "@typescript-eslint/parser": "^7.0.2",
37
+ "@changesets/changelog-github": "0.5.0",
38
+ "@changesets/cli": "2.27.1",
39
+ "@commercetools/platform-sdk": "8.8.0",
40
+ "@types/basic-auth": "1.1.8",
41
+ "@types/body-parser": "1.19.5",
42
+ "@types/deep-equal": "1.0.4",
43
+ "@types/express": "4.17.21",
44
+ "@types/express-serve-static-core": "4.17.43",
45
+ "@types/lodash.isequal": "4.5.8",
46
+ "@types/morgan": "1.9.9",
47
+ "@types/node": "20.16.14",
48
+ "@types/qs": "6.9.11",
49
+ "@types/supertest": "6.0.2",
50
+ "@types/uuid": "9.0.8",
53
51
  "@vitest/coverage-v8": "3.0.2",
54
- "esbuild": "^0.20.1",
55
- "eslint": "^8.57.1",
56
- "eslint-plugin-sort-class-members": "^1.21.0",
57
- "eslint-plugin-unused-imports": "^3.1.0",
58
- "fishery": "^2.2.2",
59
- "got": "^14.2.0",
60
- "husky": "^9.0.11",
61
- "prettier": "^3.2.5",
62
- "prettier-plugin-organize-imports": "^3.2.4",
63
- "prettier-plugin-packagejson": "^2.5.3",
64
- "supertest": "^6.3.4",
65
- "timekeeper": "^2.3.1",
66
- "ts-node": "^10.9.2",
67
- "tslib": "^2.8.0",
68
- "tsup": "^8.0.2",
69
- "typescript": "^5.6.3",
52
+ "esbuild": "0.20.1",
53
+ "fishery": "2.2.2",
54
+ "got": "14.2.0",
55
+ "husky": "9.0.11",
56
+ "supertest": "6.3.4",
57
+ "timekeeper": "2.3.1",
58
+ "ts-node": "10.9.2",
59
+ "tslib": "2.8.0",
60
+ "tsup": "8.0.2",
61
+ "typescript": "5.8.3",
70
62
  "vitest": "3.0.2"
71
63
  },
72
64
  "engines": {
@@ -79,10 +71,11 @@
79
71
  "scripts": {
80
72
  "build": "tsup",
81
73
  "build:server": "esbuild src/server.ts --bundle --outfile=dist/server.js --platform=node",
82
- "check": "pnpm lint && tsc",
83
- "format": "eslint src --fix ; prettier --write .",
84
- "lint": "eslint src && prettier --check .",
74
+ "check": "biome check && tsc",
75
+ "format": "biome format --fix",
76
+ "lint": "biome check",
85
77
  "publish:ci": "pnpm build && pnpm changeset publish",
78
+ "publish:version": "pnpm changeset version && pnpm format",
86
79
  "start": "tsup src/server.ts --watch --onSuccess 'node dist/server'",
87
80
  "test": "vitest run",
88
81
  "test:ci": "vitest run --coverage"
package/src/ctMock.ts CHANGED
@@ -182,12 +182,11 @@ export class CommercetoolsMock {
182
182
  message: err.message,
183
183
  errors: [err.info],
184
184
  });
185
- } else {
186
- console.error(err);
187
- return resp.status(500).send({
188
- error: err.message,
189
- });
190
185
  }
186
+ console.error(err);
187
+ return resp.status(500).send({
188
+ error: err.message,
189
+ });
191
190
  });
192
191
 
193
192
  return app;
@@ -210,7 +209,7 @@ export class CommercetoolsMock {
210
209
  const headers = copyHeaders(request.headers);
211
210
 
212
211
  const res = await inject(app)
213
- .post(url.pathname + "?" + url.searchParams.toString())
212
+ .post(`${url.pathname}?${url.searchParams.toString()}`)
214
213
  .body(body)
215
214
  .headers(headers)
216
215
  .end();
@@ -225,7 +224,7 @@ export class CommercetoolsMock {
225
224
  const headers = copyHeaders(request.headers);
226
225
 
227
226
  const res = await inject(app)
228
- .get(url.pathname + "?" + url.searchParams.toString())
227
+ .get(`${url.pathname}?${url.searchParams.toString()}`)
229
228
  .body(body)
230
229
  .headers(headers)
231
230
  .end();
@@ -256,7 +255,7 @@ export class CommercetoolsMock {
256
255
  const headers = copyHeaders(request.headers);
257
256
 
258
257
  const res = await inject(app)
259
- .get(url.pathname + "?" + url.searchParams.toString())
258
+ .get(`${url.pathname}?${url.searchParams.toString()}`)
260
259
  .body(body)
261
260
  .headers(headers)
262
261
  .end();
@@ -271,7 +270,7 @@ export class CommercetoolsMock {
271
270
  const headers = copyHeaders(request.headers);
272
271
 
273
272
  const res = await inject(app)
274
- .post(url.pathname + "?" + url.searchParams.toString())
273
+ .post(`${url.pathname}?${url.searchParams.toString()}`)
275
274
  .body(body)
276
275
  .headers(headers)
277
276
  .end();
@@ -286,7 +285,7 @@ export class CommercetoolsMock {
286
285
  const headers = copyHeaders(request.headers);
287
286
 
288
287
  const res = await inject(app)
289
- .delete(url.pathname + "?" + url.searchParams.toString())
288
+ .delete(`${url.pathname}?${url.searchParams.toString()}`)
290
289
  .body(body)
291
290
  .headers(headers)
292
291
  .end();
@@ -307,10 +306,9 @@ export class CommercetoolsMock {
307
306
  if (_globalListeners.length > 0) {
308
307
  if (this._mswServer !== undefined) {
309
308
  throw new Error("Server already started");
310
- } else {
311
- process.emitWarning("Server wasn't stopped properly, clearing");
312
- _globalListeners.forEach((listener) => listener.close());
313
309
  }
310
+ process.emitWarning("Server wasn't stopped properly, clearing");
311
+ _globalListeners.forEach((listener) => listener.close());
314
312
  }
315
313
 
316
314
  const server = setupServer();
package/src/index.test.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type InvalidTokenError } from "@commercetools/platform-sdk";
1
+ import type { InvalidTokenError } from "@commercetools/platform-sdk";
2
2
  import got from "got";
3
3
  import { setupServer } from "msw/node";
4
4
  import { afterEach, beforeAll, expect, test } from "vitest";
@@ -23,12 +23,12 @@ test("node:fetch client", async () => {
23
23
  });
24
24
  ctMock.registerHandlers(mswServer);
25
25
 
26
- const authHeader = "Basic " + Buffer.from("foo:bar").toString("base64");
26
+ const authHeader = `Basic ${Buffer.from("foo:bar").toString("base64")}`;
27
27
  let response = await fetch("https://localhost:8080/oauth/token", {
28
28
  method: "POST",
29
29
  headers: {
30
30
  "Content-Type": "application/x-www-form-urlencoded",
31
- "Authorization": authHeader,
31
+ Authorization: authHeader,
32
32
  },
33
33
  body: new URLSearchParams({
34
34
  grant_type: "client_credentials",
@@ -109,7 +109,7 @@ test("Options.validateCredentials: true (error)", async () => {
109
109
  "https://api.europe-west1.gcp.commercetools.com/my-project/orders",
110
110
  {
111
111
  headers: {
112
- Authorization: `Bearer foobar`,
112
+ Authorization: "Bearer foobar",
113
113
  },
114
114
  responseType: "json",
115
115
  throwHttpErrors: false,
@@ -130,7 +130,7 @@ test("Options.validateCredentials: false", async () => {
130
130
  "https://api.europe-west1.gcp.commercetools.com/my-project/orders",
131
131
  {
132
132
  headers: {
133
- Authorization: `Bearer foobar`,
133
+ Authorization: "Bearer foobar",
134
134
  },
135
135
  responseType: "json",
136
136
  },
@@ -13,8 +13,8 @@ describe("Predicate filter", () => {
13
13
  nested: {
14
14
  numberProperty: 1234,
15
15
  objectProperty: {
16
- "stringProperty": "foobar",
17
- "booleanProperty": true,
16
+ stringProperty: "foobar",
17
+ booleanProperty: true,
18
18
  "45c652f2-76e8-48fd-ab64-d11ad99d6631": {
19
19
  stringProperty: "foobar",
20
20
  uuidProperty: "3a57cc78-db08-4cd3-b778-d59b3326c435",
@@ -95,60 +95,60 @@ describe("Predicate filter", () => {
95
95
  expect(match(`stringProperty="foobar"`)).toBeTruthy();
96
96
  expect(match(`stringProperty!="foobar"`)).toBeFalsy();
97
97
 
98
- expect(match(`stringProperty=:val`, { val: "foobar" })).toBeTruthy();
98
+ expect(match("stringProperty=:val", { val: "foobar" })).toBeTruthy();
99
99
  });
100
100
 
101
101
  test("booleanProperty = true", async () => {
102
- expect(match(`booleanProperty != true`)).toBeFalsy();
103
- expect(match(`booleanProperty = true`)).toBeTruthy();
102
+ expect(match("booleanProperty != true")).toBeFalsy();
103
+ expect(match("booleanProperty = true")).toBeTruthy();
104
104
 
105
- expect(match(`booleanProperty=:val`, { val: true })).toBeTruthy();
105
+ expect(match("booleanProperty=:val", { val: true })).toBeTruthy();
106
106
  });
107
107
 
108
108
  test('stringProperty matches ignore case "foobar"', async () => {
109
109
  expect(match(`stringProperty="FOObar"`)).toBeFalsy();
110
110
  expect(match(`stringProperty matches ignore case "FOObar"`)).toBeTruthy();
111
111
  expect(
112
- match(`stringProperty matches ignore case :val`, { val: "fooBar" }),
112
+ match("stringProperty matches ignore case :val", { val: "fooBar" }),
113
113
  ).toBeTruthy();
114
114
  });
115
115
 
116
116
  test("numberProperty = 1234", async () => {
117
- expect(match(`numberProperty=1234`)).toBeTruthy();
118
- expect(match(`numberProperty = 1234`)).toBeTruthy();
119
- expect(match(`numberProperty=1230`)).toBeFalsy();
120
- expect(match(`numberProperty = 1230`)).toBeFalsy();
117
+ expect(match("numberProperty=1234")).toBeTruthy();
118
+ expect(match("numberProperty = 1234")).toBeTruthy();
119
+ expect(match("numberProperty=1230")).toBeFalsy();
120
+ expect(match("numberProperty = 1230")).toBeFalsy();
121
121
 
122
- expect(match(`numberProperty=:val`, { val: 1234 })).toBeTruthy();
122
+ expect(match("numberProperty=:val", { val: 1234 })).toBeTruthy();
123
123
  });
124
124
 
125
125
  test("numberProperty > ...", async () => {
126
- expect(match(`numberProperty > 1233`)).toBeTruthy();
127
- expect(match(`numberProperty > 1234`)).toBeFalsy();
126
+ expect(match("numberProperty > 1233")).toBeTruthy();
127
+ expect(match("numberProperty > 1234")).toBeFalsy();
128
128
  });
129
129
 
130
130
  test("numberProperty >= ...", async () => {
131
- expect(match(`numberProperty >= 1234`)).toBeTruthy();
132
- expect(match(`numberProperty >= 1235`)).toBeFalsy();
131
+ expect(match("numberProperty >= 1234")).toBeTruthy();
132
+ expect(match("numberProperty >= 1235")).toBeFalsy();
133
133
  });
134
134
 
135
135
  test("numberProperty < ...", async () => {
136
- expect(match(`numberProperty < 1235`)).toBeTruthy();
137
- expect(match(`numberProperty < 1234`)).toBeFalsy();
136
+ expect(match("numberProperty < 1235")).toBeTruthy();
137
+ expect(match("numberProperty < 1234")).toBeFalsy();
138
138
  });
139
139
 
140
140
  test("numberProperty <= ...", async () => {
141
- expect(match(`numberProperty <= 1235`)).toBeTruthy();
142
- expect(match(`numberProperty <= 1234`)).toBeTruthy();
143
- expect(match(`numberProperty <= 1233`)).toBeFalsy();
141
+ expect(match("numberProperty <= 1235")).toBeTruthy();
142
+ expect(match("numberProperty <= 1234")).toBeTruthy();
143
+ expect(match("numberProperty <= 1233")).toBeFalsy();
144
144
  });
145
145
 
146
146
  test("numberPropery in (...)", async () => {
147
- expect(match(`numberProperty in (1233, 1234, 1235)`)).toBeTruthy();
147
+ expect(match("numberProperty in (1233, 1234, 1235)")).toBeTruthy();
148
148
  });
149
149
 
150
150
  test("numberPropery in (...) single value", async () => {
151
- expect(match(`numberProperty in (1234)`)).toBeTruthy();
151
+ expect(match("numberProperty in (1234)")).toBeTruthy();
152
152
  });
153
153
 
154
154
  test("arrayProperty contains all (...)", async () => {
@@ -159,17 +159,17 @@ describe("Predicate filter", () => {
159
159
  });
160
160
 
161
161
  test("arrayProperty is empty", async () => {
162
- expect(match(`arrayProperty is empty`)).toBeFalsy();
163
- expect(match(`arrayProperty is not empty`)).toBeTruthy();
164
- expect(match(`emptyArrayProperty is empty`)).toBeTruthy();
162
+ expect(match("arrayProperty is empty")).toBeFalsy();
163
+ expect(match("arrayProperty is not empty")).toBeTruthy();
164
+ expect(match("emptyArrayProperty is empty")).toBeTruthy();
165
165
  });
166
166
 
167
167
  test("property is defined", async () => {
168
- expect(match(`notDefined is defined`)).toBeFalsy();
169
- expect(match(`notDefined is not defined`)).toBeTruthy();
168
+ expect(match("notDefined is defined")).toBeFalsy();
169
+ expect(match("notDefined is not defined")).toBeTruthy();
170
170
 
171
- expect(match(`arrayProperty is defined`)).toBeTruthy();
172
- expect(match(`arrayProperty is not defined`)).toBeFalsy();
171
+ expect(match("arrayProperty is defined")).toBeTruthy();
172
+ expect(match("arrayProperty is not defined")).toBeFalsy();
173
173
  });
174
174
 
175
175
  test("arrayProperty contains any (...)", async () => {
@@ -186,14 +186,14 @@ describe("Predicate filter", () => {
186
186
  expect(match(`nested(array(stringProperty="foobar"))`)).toBeFalsy();
187
187
 
188
188
  // Different comparison operators
189
- expect(match(`nested(array(numberProperty>=2345))`)).toBeTruthy();
190
- expect(match(`nested(array(numberProperty>=2346))`)).toBeFalsy();
191
- expect(match(`nested(array(numberProperty>2344))`)).toBeTruthy();
192
- expect(match(`nested(array(numberProperty>2345))`)).toBeFalsy();
193
- expect(match(`nested(array(numberProperty<=1234))`)).toBeTruthy();
194
- expect(match(`nested(array(numberProperty<=1233))`)).toBeFalsy();
195
- expect(match(`nested(array(numberProperty<1235))`)).toBeTruthy();
196
- expect(match(`nested(array(numberProperty<1234))`)).toBeFalsy();
189
+ expect(match("nested(array(numberProperty>=2345))")).toBeTruthy();
190
+ expect(match("nested(array(numberProperty>=2346))")).toBeFalsy();
191
+ expect(match("nested(array(numberProperty>2344))")).toBeTruthy();
192
+ expect(match("nested(array(numberProperty>2345))")).toBeFalsy();
193
+ expect(match("nested(array(numberProperty<=1234))")).toBeTruthy();
194
+ expect(match("nested(array(numberProperty<=1233))")).toBeFalsy();
195
+ expect(match("nested(array(numberProperty<1235))")).toBeTruthy();
196
+ expect(match("nested(array(numberProperty<1234))")).toBeFalsy();
197
197
 
198
198
  // One level deeper
199
199
  expect(
@@ -246,57 +246,57 @@ describe("Predicate filter", () => {
246
246
  test("geolocation within circle (...)", async () => {
247
247
  expect(
248
248
  match(
249
- `geoLocation within circle(5.121310867198959, 52.09068804569714, 2500)`,
249
+ "geoLocation within circle(5.121310867198959, 52.09068804569714, 2500)",
250
250
  ),
251
251
  ).toBeTruthy();
252
252
  expect(
253
253
  match(
254
- `geoLocation within circle(5.121310867198959, 52.09068804569714, 2400)`,
254
+ "geoLocation within circle(5.121310867198959, 52.09068804569714, 2400)",
255
255
  ),
256
256
  ).toBeFalsy();
257
257
  });
258
258
 
259
259
  test("negate any other conditional expression", async () => {
260
- expect(match(`numberProperty = 1234`)).toBeTruthy();
261
- expect(match(`not (numberProperty = 1234)`)).toBeFalsy();
262
- expect(match(`not (numberProperty = 1235)`)).toBeTruthy();
263
- expect(match(`not (numberProperty = 1235)`)).toBeTruthy();
264
-
265
- expect(match(`nested(numberProperty=1234))`)).toBeTruthy();
266
- expect(match(`nested(not(numberProperty=1230)))`)).toBeTruthy();
267
- expect(match(`nested(not(numberProperty=1234)))`)).toBeFalsy();
260
+ expect(match("numberProperty = 1234")).toBeTruthy();
261
+ expect(match("not (numberProperty = 1234)")).toBeFalsy();
262
+ expect(match("not (numberProperty = 1235)")).toBeTruthy();
263
+ expect(match("not (numberProperty = 1235)")).toBeTruthy();
264
+
265
+ expect(match("nested(numberProperty=1234))")).toBeTruthy();
266
+ expect(match("nested(not(numberProperty=1230)))")).toBeTruthy();
267
+ expect(match("nested(not(numberProperty=1234)))")).toBeFalsy();
268
268
  });
269
269
 
270
270
  test("and clause (implicit)", async () => {
271
271
  expect(
272
- match([`stringProperty="foobar"`, `numberProperty=1234`]),
272
+ match([`stringProperty="foobar"`, "numberProperty=1234"]),
273
273
  ).toBeTruthy();
274
274
 
275
275
  expect(
276
- match([`stringProperty="foobar"`, `numberProperty=1111`]),
276
+ match([`stringProperty="foobar"`, "numberProperty=1111"]),
277
277
  ).toBeFalsy();
278
278
  });
279
279
 
280
280
  test("and clause (explicit)", async () => {
281
- expect(match(`numberProperty>1233 and numberProperty<1235`)).toBeTruthy();
282
- expect(match(`numberProperty>1233 and numberProperty<1234`)).toBeFalsy();
281
+ expect(match("numberProperty>1233 and numberProperty<1235")).toBeTruthy();
282
+ expect(match("numberProperty>1233 and numberProperty<1234")).toBeFalsy();
283
283
  });
284
284
 
285
285
  test("or clause", async () => {
286
286
  expect(
287
287
  match(
288
- `numberProperty=1231 or numberProperty>54312 or numberProperty=1234`,
288
+ "numberProperty=1231 or numberProperty>54312 or numberProperty=1234",
289
289
  ),
290
290
  ).toBeTruthy();
291
- expect(match(`numberProperty=1231 or numberProperty=1234`)).toBeTruthy();
292
- expect(match(`numberProperty=1231 or (numberProperty=1234)`)).toBeTruthy();
293
- expect(match(`numberProperty=1233 or numberProperty=1235`)).toBeFalsy();
291
+ expect(match("numberProperty=1231 or numberProperty=1234")).toBeTruthy();
292
+ expect(match("numberProperty=1231 or (numberProperty=1234)")).toBeTruthy();
293
+ expect(match("numberProperty=1233 or numberProperty=1235")).toBeFalsy();
294
294
  });
295
295
 
296
296
  test("or / and clause mixed", async () => {
297
297
  expect(
298
298
  match(
299
- `numberProperty=1234 and (numberProperty=1230 or (numberProperty=1234 or numberProperty=1235))`,
299
+ "numberProperty=1234 and (numberProperty=1230 or (numberProperty=1234 or numberProperty=1235))",
300
300
  ),
301
301
  ).toBeTruthy();
302
302
  });
@@ -308,10 +308,10 @@ describe("Predicate filter", () => {
308
308
 
309
309
  test("nested attribute access", async () => {
310
310
  expect(
311
- match(`nested(objectProperty(booleanProperty != true))`),
311
+ match("nested(objectProperty(booleanProperty != true))"),
312
312
  ).toBeFalsy();
313
313
  expect(
314
- match(`nested(objectProperty(booleanProperty != false))`),
314
+ match("nested(objectProperty(booleanProperty != false))"),
315
315
  ).toBeTruthy();
316
316
  });
317
317
 
@@ -329,11 +329,11 @@ describe("Predicate filter", () => {
329
329
  // })
330
330
 
331
331
  test("invalid predicate", async () => {
332
- expect(() => match(`stringProperty=nomatch`)).toThrow(PredicateError);
333
- expect(() => match(`stringProperty=nomatch`)).toThrow(
332
+ expect(() => match("stringProperty=nomatch")).toThrow(PredicateError);
333
+ expect(() => match("stringProperty=nomatch")).toThrow(
334
334
  "Invalid input 'n', expected input parameter or primitive value (line 1, column 16)",
335
335
  );
336
- expect(() => match(`stringProperty`)).toThrow(PredicateError);
336
+ expect(() => match("stringProperty")).toThrow(PredicateError);
337
337
  });
338
338
 
339
339
  test("uuid as field name", async () => {
@@ -5,7 +5,7 @@
5
5
  * See https://docs.commercetools.com/api/predicates/query
6
6
  */
7
7
  import { haversineDistance } from "./haversine";
8
- import { Lexer, Parser, type ITokenPosition } from "./parser";
8
+ import { type ITokenPosition, Lexer, Parser } from "./parser";
9
9
 
10
10
  export class PredicateError {
11
11
  message: string;
@@ -34,10 +34,9 @@ export const matchesPredicate = (
34
34
  const func = generateMatchFunc(item);
35
35
  return func(target, variables ?? {});
36
36
  });
37
- } else {
38
- const func = generateMatchFunc(predicate);
39
- return func(target, variables ?? {});
40
37
  }
38
+ const func = generateMatchFunc(predicate);
39
+ return func(target, variables ?? {});
41
40
  };
42
41
 
43
42
  export const parseQueryExpression = (
@@ -47,9 +46,8 @@ export const parseQueryExpression = (
47
46
  const callbacks = predicate.map((item) => generateMatchFunc(item));
48
47
  return (target: any, variables: VariableMap) =>
49
48
  callbacks.every((callback) => callback(target, variables));
50
- } else {
51
- return generateMatchFunc(predicate);
52
49
  }
50
+ return generateMatchFunc(predicate);
53
51
  };
54
52
 
55
53
  type TypeSymbol = {
@@ -177,7 +175,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
177
175
  (t) =>
178
176
  ({
179
177
  type: "boolean",
180
- value: t.token.match === "true" ? true : false,
178
+ value: t.token.match === "true",
181
179
  pos: t.token.strpos(),
182
180
  }) as TypeSymbol,
183
181
  )
@@ -209,7 +207,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
209
207
  (t) =>
210
208
  ({
211
209
  type: "int",
212
- value: parseInt(t.token.match, 10),
210
+ value: Number.parseInt(t.token.match, 10),
213
211
  pos: t.token.strpos(),
214
212
  }) as TypeSymbol,
215
213
  )
@@ -219,7 +217,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
219
217
  (t) =>
220
218
  ({
221
219
  type: "float",
222
- value: parseFloat(t.token.match),
220
+ value: Number.parseFloat(t.token.match),
223
221
  pos: t.token.strpos(),
224
222
  }) as TypeSymbol,
225
223
  )
@@ -242,9 +240,8 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
242
240
  const expr: any = parser.parse({ terminals: [bp - 1] });
243
241
  if (Array.isArray(expr)) {
244
242
  return [left, ...expr];
245
- } else {
246
- return [left, expr];
247
243
  }
244
+ return [left, expr];
248
245
  })
249
246
  .nud("(", 100, (t) => {
250
247
  const expr: any = parser.parse({ terminals: [")"] });
@@ -262,17 +259,16 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
262
259
  }
263
260
  return false;
264
261
  });
265
- } else {
266
- const value = resolveValue(obj, left);
267
- if (value) {
268
- if (Array.isArray(value)) {
269
- return value.some((item) => expr(item, vars));
270
- }
271
-
272
- return expr(value, vars);
262
+ }
263
+ const value = resolveValue(obj, left);
264
+ if (value) {
265
+ if (Array.isArray(value)) {
266
+ return value.some((item) => expr(item, vars));
273
267
  }
274
- return false;
268
+
269
+ return expr(value, vars);
275
270
  }
271
+ return false;
276
272
  };
277
273
  })
278
274
  .bp(")", 0)
@@ -290,14 +286,13 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
290
286
  }
291
287
  return value === other;
292
288
  });
293
- } else {
294
- const resolvedValue = resolveValue(obj, left);
295
- const resolvedSymbol = resolveSymbol(expr, vars);
296
- if (Array.isArray(resolvedValue)) {
297
- return !!resolvedValue.some((elem) => elem === resolvedSymbol);
298
- }
299
- return resolvedValue === resolvedSymbol;
300
289
  }
290
+ const resolvedValue = resolveValue(obj, left);
291
+ const resolvedSymbol = resolveSymbol(expr, vars);
292
+ if (Array.isArray(resolvedValue)) {
293
+ return !!resolvedValue.some((elem) => elem === resolvedSymbol);
294
+ }
295
+ return resolvedValue === resolvedSymbol;
301
296
  };
302
297
  })
303
298
  .led("!=", 20, ({ left, bp }) => {
@@ -353,12 +348,11 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
353
348
  const val = resolveValue(obj, left);
354
349
  return val.length === 0;
355
350
  };
356
- } else {
357
- return (obj: any, vars: VariableMap) => {
358
- const val = resolveValue(obj, left);
359
- return val.length !== 0;
360
- };
361
351
  }
352
+ return (obj: any, vars: VariableMap) => {
353
+ const val = resolveValue(obj, left);
354
+ return val.length !== 0;
355
+ };
362
356
  }
363
357
  case "defined": {
364
358
  if (!invert) {
@@ -366,12 +360,11 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
366
360
  const val = resolveValue(obj, left);
367
361
  return val !== undefined;
368
362
  };
369
- } else {
370
- return (obj: any, vars: VariableMap) => {
371
- const val = resolveValue(obj, left);
372
- return val === undefined;
373
- };
374
363
  }
364
+ return (obj: any, vars: VariableMap) => {
365
+ const val = resolveValue(obj, left);
366
+ return val === undefined;
367
+ };
375
368
  }
376
369
  default: {
377
370
  throw new Error("Unexpected");
@@ -463,9 +456,8 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
463
456
  const array = expr.map((item: TypeSymbol) => resolveSymbol(item, vars));
464
457
  if (keyword.type === "ALL") {
465
458
  return array.every((item: any) => value.includes(item));
466
- } else {
467
- return array.some((item: any) => value.includes(item));
468
459
  }
460
+ return array.some((item: any) => value.includes(item));
469
461
  };
470
462
  })
471
463
 
@@ -478,9 +470,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
478
470
  const column = lines[lines.length - 1].length;
479
471
 
480
472
  throw new PredicateError(
481
- `Unexpected end of input, expected SphereIdentifierChar, comparison ` +
482
- `operator, not, in, contains, is, within or matches` +
483
- ` (line ${lines.length}, column ${column})`,
473
+ `Unexpected end of input, expected SphereIdentifierChar, comparison operator, not, in, contains, is, within or matches (line ${lines.length}, column ${column})`,
484
474
  );
485
475
  }
486
476
  return result;
@@ -138,6 +138,24 @@ describe("Product search filter", () => {
138
138
  },
139
139
  }).isMatch,
140
140
  ).toBeTruthy();
141
+
142
+ expect(
143
+ match({
144
+ exact: {
145
+ field: "variants.sku",
146
+ values: ["MYSKU", "OTHER"],
147
+ },
148
+ }).isMatch,
149
+ ).toBeTruthy();
150
+
151
+ expect(
152
+ match({
153
+ exact: {
154
+ field: "variants.sku",
155
+ values: ["OTHER"],
156
+ },
157
+ }).isMatch,
158
+ ).toBeFalsy();
141
159
  });
142
160
 
143
161
  test("by attribute value", async () => {