@labdigital/commercetools-mock 0.9.1 → 0.10.1

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 (108) hide show
  1. package/README.md +8 -0
  2. package/dist/index.d.ts +354 -188
  3. package/dist/index.global.js +2346 -2209
  4. package/dist/index.global.js.map +1 -1
  5. package/dist/index.js +1968 -1829
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +2171 -2032
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +30 -21
  10. package/src/constants.ts +4 -2
  11. package/src/ctMock.ts +27 -86
  12. package/src/helpers.ts +10 -11
  13. package/src/index.test.ts +1 -1
  14. package/src/lib/haversine.ts +2 -2
  15. package/src/lib/masking.ts +3 -1
  16. package/src/lib/predicateParser.ts +93 -92
  17. package/src/lib/projectionSearchFilter.test.ts +28 -36
  18. package/src/lib/projectionSearchFilter.ts +88 -103
  19. package/src/oauth/store.ts +3 -3
  20. package/src/priceSelector.test.ts +16 -35
  21. package/src/priceSelector.ts +6 -9
  22. package/src/product-projection-search.ts +49 -57
  23. package/src/projectAPI.test.ts +7 -0
  24. package/src/projectAPI.ts +17 -22
  25. package/src/repositories/abstract.ts +102 -51
  26. package/src/repositories/cart-discount.ts +4 -5
  27. package/src/repositories/cart.ts +56 -46
  28. package/src/repositories/category.ts +23 -26
  29. package/src/repositories/channel.ts +5 -6
  30. package/src/repositories/custom-object.ts +41 -32
  31. package/src/repositories/customer-group.ts +4 -5
  32. package/src/repositories/customer.ts +42 -5
  33. package/src/repositories/discount-code.ts +5 -6
  34. package/src/repositories/errors.ts +10 -14
  35. package/src/repositories/extension.ts +16 -15
  36. package/src/repositories/helpers.ts +10 -15
  37. package/src/repositories/index.ts +75 -0
  38. package/src/repositories/inventory-entry.ts +5 -6
  39. package/src/repositories/my-order.ts +2 -2
  40. package/src/repositories/order-edit.ts +39 -0
  41. package/src/repositories/order.test.ts +16 -11
  42. package/src/repositories/order.ts +21 -14
  43. package/src/repositories/payment.ts +9 -10
  44. package/src/repositories/product-discount.ts +5 -25
  45. package/src/repositories/product-projection.ts +12 -5
  46. package/src/repositories/product-selection.ts +40 -0
  47. package/src/repositories/product-type.ts +38 -60
  48. package/src/repositories/product.ts +128 -85
  49. package/src/repositories/project.ts +16 -33
  50. package/src/repositories/quote-request.ts +28 -0
  51. package/src/repositories/quote.ts +28 -0
  52. package/src/repositories/review.ts +34 -0
  53. package/src/repositories/shipping-method.ts +25 -28
  54. package/src/repositories/shopping-list.ts +6 -6
  55. package/src/repositories/staged-quote.ts +29 -0
  56. package/src/repositories/standalone-price.ts +36 -0
  57. package/src/repositories/state.ts +16 -17
  58. package/src/repositories/store.ts +13 -29
  59. package/src/repositories/subscription.ts +4 -5
  60. package/src/repositories/tax-category.ts +9 -26
  61. package/src/repositories/type.ts +24 -27
  62. package/src/repositories/zone.ts +9 -11
  63. package/src/server.ts +5 -0
  64. package/src/services/abstract.ts +43 -12
  65. package/src/services/cart-discount.ts +3 -4
  66. package/src/services/cart.test.ts +9 -11
  67. package/src/services/cart.ts +42 -38
  68. package/src/services/category.test.ts +1 -2
  69. package/src/services/category.ts +3 -4
  70. package/src/services/channel.ts +3 -4
  71. package/src/services/custom-object.test.ts +6 -6
  72. package/src/services/custom-object.ts +4 -5
  73. package/src/services/customer-group.ts +3 -4
  74. package/src/services/customer.test.ts +136 -0
  75. package/src/services/customer.ts +5 -6
  76. package/src/services/discount-code.ts +3 -4
  77. package/src/services/extension.ts +3 -4
  78. package/src/services/index.ts +74 -0
  79. package/src/services/inventory-entry.test.ts +9 -13
  80. package/src/services/inventory-entry.ts +3 -4
  81. package/src/services/my-cart.test.ts +2 -0
  82. package/src/services/my-cart.ts +4 -5
  83. package/src/services/my-customer.ts +3 -4
  84. package/src/services/my-order.ts +4 -5
  85. package/src/services/my-payment.ts +3 -4
  86. package/src/services/order.test.ts +28 -26
  87. package/src/services/order.ts +4 -5
  88. package/src/services/payment.ts +3 -4
  89. package/src/services/product-discount.ts +3 -20
  90. package/src/services/product-projection.test.ts +76 -8
  91. package/src/services/product-projection.ts +4 -5
  92. package/src/services/product-type.ts +3 -20
  93. package/src/services/product.test.ts +200 -90
  94. package/src/services/product.ts +3 -4
  95. package/src/services/project.ts +5 -6
  96. package/src/services/shipping-method.ts +3 -4
  97. package/src/services/shopping-list.ts +3 -4
  98. package/src/services/state.ts +3 -4
  99. package/src/services/store.test.ts +11 -2
  100. package/src/services/store.ts +4 -21
  101. package/src/services/subscription.ts +3 -4
  102. package/src/services/tax-category.ts +3 -20
  103. package/src/services/type.ts +3 -4
  104. package/src/services/zone.ts +3 -4
  105. package/src/storage/abstract.ts +82 -0
  106. package/src/{storage.ts → storage/in-memory.ts} +79 -147
  107. package/src/storage/index.ts +2 -0
  108. package/src/types.ts +52 -83
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
- "version": "0.9.1",
2
+ "name": "@labdigital/commercetools-mock",
3
+ "author": "Michael van Tellingen",
4
+ "version": "0.10.1",
3
5
  "license": "MIT",
4
6
  "main": "dist/index.js",
7
+ "module": "dist/commercetools--mock.esm.js",
5
8
  "typings": "dist/index.d.ts",
6
9
  "files": [
7
10
  "dist",
@@ -14,21 +17,35 @@
14
17
  }
15
18
  },
16
19
  "engines": {
17
- "node": ">=14"
20
+ "node": ">=14",
21
+ "pnpm": ">=7.13.2"
18
22
  },
23
+ "packageManager": "pnpm@7.13.2",
19
24
  "prettier": {
20
25
  "printWidth": 80,
21
26
  "semi": false,
22
27
  "singleQuote": true,
23
28
  "trailingComma": "es5"
24
29
  },
25
- "name": "@labdigital/commercetools-mock",
26
- "author": "Michael van Tellingen",
27
- "module": "dist/commercetools--mock.esm.js",
30
+ "dependencies": {
31
+ "@types/lodash": "^4.14.182",
32
+ "basic-auth": "^2.0.1",
33
+ "body-parser": "^1.20.0",
34
+ "deep-equal": "^2.0.5",
35
+ "express": "^4.17.2",
36
+ "lodash": "^4.17.21",
37
+ "morgan": "^1.10.0",
38
+ "nock": "^13.2.1",
39
+ "perplex": "^0.11.0",
40
+ "pratt": "^0.7.0",
41
+ "supertest": "^6.1.6",
42
+ "type-fest": "^3.1.0",
43
+ "uuid": "^8.3.2"
44
+ },
28
45
  "devDependencies": {
29
46
  "@babel/preset-env": "^7.18.9",
30
47
  "@babel/preset-typescript": "^7.18.6",
31
- "@commercetools/platform-sdk": "2.8.0",
48
+ "@commercetools/platform-sdk": "4.0.0",
32
49
  "@types/basic-auth": "^1.1.3",
33
50
  "@types/body-parser": "^1.19.2",
34
51
  "@types/deep-equal": "^1.0.1",
@@ -40,13 +57,17 @@
40
57
  "@types/qs": "^6.9.7",
41
58
  "@types/supertest": "^2.0.11",
42
59
  "@types/uuid": "^8.3.4",
60
+ "@typescript-eslint/eslint-plugin": "^5.39.0",
61
+ "@typescript-eslint/parser": "^5.39.0",
43
62
  "esbuild": "^0.14.50",
44
63
  "esbuild-register": "^3.3.1",
45
64
  "eslint": "^8.20.0",
65
+ "eslint-plugin-unused-imports": "^2.0.0",
46
66
  "got": "^11.8.3",
47
67
  "husky": "^7.0.4",
48
68
  "jest": "^28.1.3",
49
69
  "nodemon": "^2.0.15",
70
+ "prettier": "^2.7.1",
50
71
  "timekeeper": "^2.2.0",
51
72
  "ts-node": "^10.4.0",
52
73
  "tsc": "^2.0.4",
@@ -54,27 +75,15 @@
54
75
  "tsup": "^6.2.0",
55
76
  "typescript": "^4.7.4"
56
77
  },
57
- "dependencies": {
58
- "@types/lodash": "^4.14.182",
59
- "basic-auth": "^2.0.1",
60
- "body-parser": "^1.20.0",
61
- "deep-equal": "^2.0.5",
62
- "express": "^4.17.2",
63
- "lodash": "^4.17.21",
64
- "morgan": "^1.10.0",
65
- "nock": "^13.2.1",
66
- "perplex": "^0.11.0",
67
- "pratt": "^0.7.0",
68
- "supertest": "^6.1.6",
69
- "uuid": "^8.3.2"
70
- },
71
78
  "peerDependencies": {
72
79
  "@commercetools/platform-sdk": "^2.4.1"
73
80
  },
74
81
  "scripts": {
75
82
  "start": "nodemon --watch src --exec 'node -r esbuild-register' src/server.ts",
76
83
  "build": "tsup",
84
+ "build:server": "esbuild src/server.ts --bundle --outfile=dist/server.js --platform=node",
85
+ "check": "eslint src && tsc",
77
86
  "test": "jest test --coverage",
78
- "lint": "eslint"
87
+ "lint": "eslint src"
79
88
  }
80
89
  }
package/src/constants.ts CHANGED
@@ -1,2 +1,4 @@
1
- export const DEFAULT_API_HOSTNAME = /^https:\/\/api\..*?\.commercetools.com:443$/
2
- export const DEFAULT_AUTH_HOSTNAME = /^https:\/\/auth\..*?\.commercetools.com:443$/
1
+ export const DEFAULT_API_HOSTNAME =
2
+ /^https:\/\/api\..*?\.commercetools.com:443$/
3
+ export const DEFAULT_AUTH_HOSTNAME =
4
+ /^https:\/\/auth\..*?\.commercetools.com:443$/
package/src/ctMock.ts CHANGED
@@ -11,35 +11,10 @@ import { copyHeaders } from './lib/proxy'
11
11
  import { DEFAULT_API_HOSTNAME, DEFAULT_AUTH_HOSTNAME } from './constants'
12
12
 
13
13
  // Services
14
- import { CartDiscountService } from './services/cart-discount'
15
- import { CartService } from './services/cart'
16
- import { CategoryServices } from './services/category'
17
- import { ChannelService } from './services/channel'
18
- import { CustomerGroupService } from './services/customer-group'
19
- import { CustomerService } from './services/customer'
20
- import { CustomObjectService } from './services/custom-object'
21
- import { DiscountCodeService } from './services/discount-code'
22
- import { ExtensionServices } from './services/extension'
23
- import { InventoryEntryService } from './services/inventory-entry'
24
- import { MyCartService } from './services/my-cart'
25
- import { MyPaymentService } from './services/my-payment'
26
- import { OrderService } from './services/order'
27
- import { PaymentService } from './services/payment'
28
- import { ProductDiscountService } from './services/product-discount'
29
- import { ProductProjectionService } from './services/product-projection'
30
- import { ProductService } from './services/product'
31
- import { ProductTypeService } from './services/product-type'
32
14
  import { ProjectService } from './services/project'
33
- import { ShippingMethodService } from './services/shipping-method'
34
- import { ShoppingListService } from './services/shopping-list'
35
- import { StateService } from './services/state'
36
- import { StoreService } from './services/store'
37
- import { SubscriptionService } from './services/subscription'
38
- import { TaxCategoryService } from './services/tax-category'
39
- import { TypeService } from './services/type'
40
- import { ZoneService } from './services/zone'
41
- import { MyCustomerService } from './services/my-customer'
42
- import { MyOrderService } from './services/my-order'
15
+ import { createRepositories, RepositoryMap } from './repositories'
16
+ import { createServices } from './services'
17
+ import { ProjectRepository } from 'repositories/project'
43
18
 
44
19
  export type CommercetoolsMockOptions = {
45
20
  validateCredentials: boolean
@@ -71,12 +46,14 @@ export class CommercetoolsMock {
71
46
  auth: nock.Scope | undefined
72
47
  api: nock.Scope | undefined
73
48
  } = { auth: undefined, api: undefined }
74
- private _services: Services
49
+ private _services: Services | null
50
+ private _repositories: RepositoryMap | null
75
51
  private _projectService?: ProjectService
76
52
 
77
53
  constructor(options: Partial<CommercetoolsMockOptions> = {}) {
78
54
  this.options = { ...DEFAULT_OPTIONS, ...options }
79
- this._services = {}
55
+ this._services = null
56
+ this._repositories = null
80
57
  this._projectService = undefined
81
58
 
82
59
  this._storage = new InMemoryStorage()
@@ -111,22 +88,27 @@ export class CommercetoolsMock {
111
88
  throw new Error('No projectKey passed and no default set')
112
89
  }
113
90
 
91
+ if (this._repositories === null) {
92
+ throw new Error('repositories not initialized yet')
93
+ }
94
+
114
95
  return new ProjectAPI(
115
96
  projectKey || this.options.defaultProjectKey!,
116
- this._services,
97
+ this._repositories,
117
98
  this._storage
118
99
  )
119
100
  }
120
101
 
121
- runServer(port: number = 3000, options?: AppOptions) {
122
- const app = this.createApp(options)
123
- const server = app.listen(port, () => {
124
- console.log(`Mock server listening at http://localhost:${port}`)
102
+ runServer(port = 3000, options?: AppOptions) {
103
+ const server = this.app.listen(port, () => {
104
+ console.info(`Mock server listening at http://localhost:${port}`)
125
105
  })
126
106
  server.keepAliveTimeout = 60 * 1000
127
107
  }
128
108
 
129
109
  private createApp(options?: AppOptions): express.Express {
110
+ this._repositories = createRepositories(this._storage)
111
+
130
112
  const app = express()
131
113
 
132
114
  const projectRouter = express.Router({ mergeParams: true })
@@ -150,53 +132,12 @@ export class CommercetoolsMock {
150
132
  app.use('/:projectKey/in-store/key=:storeKey', projectRouter)
151
133
  }
152
134
 
153
- this._projectService = new ProjectService(projectRouter, this._storage)
154
-
155
- this._services = {
156
- category: new CategoryServices(projectRouter, this._storage),
157
- cart: new CartService(projectRouter, this._storage),
158
- 'cart-discount': new CartDiscountService(projectRouter, this._storage),
159
- customer: new CustomerService(projectRouter, this._storage),
160
- channel: new ChannelService(projectRouter, this._storage),
161
- 'customer-group': new CustomerGroupService(projectRouter, this._storage),
162
- 'discount-code': new DiscountCodeService(projectRouter, this._storage),
163
- extension: new ExtensionServices(projectRouter, this._storage),
164
- 'inventory-entry': new InventoryEntryService(
165
- projectRouter,
166
- this._storage
167
- ),
168
- 'key-value-document': new CustomObjectService(
169
- projectRouter,
170
- this._storage
171
- ),
172
- order: new OrderService(projectRouter, this._storage),
173
- payment: new PaymentService(projectRouter, this._storage),
174
- 'my-cart': new MyCartService(projectRouter, this._storage),
175
- 'my-order': new MyOrderService(projectRouter, this._storage),
176
- 'my-customer': new MyCustomerService(projectRouter, this._storage),
177
- 'my-payment': new MyPaymentService(projectRouter, this._storage),
178
- 'shipping-method': new ShippingMethodService(
179
- projectRouter,
180
- this._storage
181
- ),
182
- 'product-type': new ProductTypeService(projectRouter, this._storage),
183
- product: new ProductService(projectRouter, this._storage),
184
- 'product-discount': new ProductDiscountService(
185
- projectRouter,
186
- this._storage
187
- ),
188
- 'product-projection': new ProductProjectionService(
189
- projectRouter,
190
- this._storage
191
- ),
192
- 'shopping-list': new ShoppingListService(projectRouter, this._storage),
193
- state: new StateService(projectRouter, this._storage),
194
- store: new StoreService(projectRouter, this._storage),
195
- subscription: new SubscriptionService(projectRouter, this._storage),
196
- 'tax-category': new TaxCategoryService(projectRouter, this._storage),
197
- type: new TypeService(projectRouter, this._storage),
198
- zone: new ZoneService(projectRouter, this._storage),
199
- }
135
+ // Register the rest api services in the router
136
+ this._services = createServices(projectRouter, this._repositories)
137
+ this._projectService = new ProjectService(
138
+ projectRouter,
139
+ this._repositories.project as ProjectRepository
140
+ )
200
141
 
201
142
  app.use((err: Error, req: Request, resp: Response, next: NextFunction) => {
202
143
  if (err instanceof CommercetoolsError) {
@@ -222,14 +163,14 @@ export class CommercetoolsMock {
222
163
  this._nockScopes.api = nock(this.options.apiHost)
223
164
  .persist()
224
165
  .get(/.*/)
225
- .reply(async function(uri) {
166
+ .reply(async function (uri) {
226
167
  const response = await supertest(app)
227
168
  .get(uri)
228
169
  .set(copyHeaders(this.req.headers))
229
170
  return [response.status, response.body]
230
171
  })
231
172
  .post(/.*/)
232
- .reply(async function(uri, body) {
173
+ .reply(async function (uri, body) {
233
174
  const response = await supertest(app)
234
175
  .post(uri)
235
176
  .set(copyHeaders(this.req.headers))
@@ -237,7 +178,7 @@ export class CommercetoolsMock {
237
178
  return [response.status, response.body]
238
179
  })
239
180
  .delete(/.*/)
240
- .reply(async function(uri, body) {
181
+ .reply(async function (uri, body) {
241
182
  const response = await supertest(app)
242
183
  .delete(uri)
243
184
  .set(copyHeaders(this.req.headers))
@@ -252,7 +193,7 @@ export class CommercetoolsMock {
252
193
  this._nockScopes.auth = nock(this.options.authHost)
253
194
  .persist()
254
195
  .post(/^\/oauth\/.*/)
255
- .reply(async function(uri, body) {
196
+ .reply(async function (uri, body) {
256
197
  const response = await supertest(app)
257
198
  .post(uri + '?' + body)
258
199
  .set(copyHeaders(this.req.headers))
package/src/helpers.ts CHANGED
@@ -1,15 +1,12 @@
1
- import { v4 as uuidv4 } from 'uuid'
2
1
  import { ParsedQs } from 'qs'
3
- import { Price } from '@commercetools/platform-sdk'
4
-
5
- export const getBaseResourceProperties = () => {
6
- return {
7
- id: uuidv4(),
8
- createdAt: new Date().toISOString(),
9
- lastModifiedAt: new Date().toISOString(),
10
- version: 0,
11
- }
12
- }
2
+ import { v4 as uuidv4 } from 'uuid'
3
+
4
+ export const getBaseResourceProperties = () => ({
5
+ id: uuidv4(),
6
+ createdAt: new Date().toISOString(),
7
+ lastModifiedAt: new Date().toISOString(),
8
+ version: 0,
9
+ })
13
10
 
14
11
  /**
15
12
  * Do a nested lookup by using a path. For example `foo.bar.value` will
@@ -47,3 +44,5 @@ export const QueryParamsAsArray = (
47
44
  }
48
45
  return [input] as string[]
49
46
  }
47
+
48
+ export const cloneObject = <T>(o: T): T => JSON.parse(JSON.stringify(o))
package/src/index.test.ts CHANGED
@@ -158,7 +158,7 @@ test('Options.authHost: is set', async () => {
158
158
  })
159
159
  ctMock.start()
160
160
 
161
- let response = await got.post<{ access_token: string }>(
161
+ const response = await got.post<{ access_token: string }>(
162
162
  'http://auth.localhost/oauth/token',
163
163
  {
164
164
  searchParams: {
@@ -13,12 +13,12 @@ export const haversineDistance = (src: Location, dst: Location) => {
13
13
  const dLat = toRadian(dst.latitude - src.latitude)
14
14
  const dLon = toRadian(dst.longitude - src.longitude)
15
15
 
16
- var a =
16
+ const a =
17
17
  Math.sin(dLat / 2) * Math.sin(dLat / 2) +
18
18
  Math.cos(toRadian(src.latitude)) *
19
19
  Math.cos(toRadian(dst.latitude)) *
20
20
  Math.sin(dLon / 2) *
21
21
  Math.sin(dLon / 2)
22
- var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
22
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
23
23
  return RADIUS_OF_EARTH_IN_KM * c * 1000
24
24
  }
@@ -1,6 +1,8 @@
1
+ import { cloneObject } from '../helpers'
2
+
1
3
  export const maskSecretValue = <T>(resource: T, path: string): T => {
2
4
  const parts = path.split('.')
3
- const clone = JSON.parse(JSON.stringify(resource))
5
+ const clone = cloneObject(resource) as any
4
6
  let val = clone
5
7
 
6
8
  const target = parts.pop()
@@ -31,7 +31,7 @@ export const matchesPredicate = (
31
31
  }
32
32
 
33
33
  if (Array.isArray(predicate)) {
34
- return predicate.every(item => {
34
+ return predicate.every((item) => {
35
35
  const func = generateMatchFunc(item)
36
36
  return func(target, variables || {})
37
37
  })
@@ -45,22 +45,21 @@ export const parseQueryExpression = (
45
45
  predicate: string | string[]
46
46
  ): MatchFunc => {
47
47
  if (Array.isArray(predicate)) {
48
- const callbacks = predicate.map(item => generateMatchFunc(item))
49
- return (target: any, variables: VariableMap) => {
50
- return callbacks.every(callback => callback(target, variables))
51
- }
48
+ const callbacks = predicate.map((item) => generateMatchFunc(item))
49
+ return (target: any, variables: VariableMap) =>
50
+ callbacks.every((callback) => callback(target, variables))
52
51
  } else {
53
52
  return generateMatchFunc(predicate)
54
53
  }
55
54
  }
56
55
 
57
- type Symbol = {
56
+ type TypeSymbol = {
58
57
  type: 'var' | 'boolean' | 'string' | 'float' | 'int' | 'identifier'
59
58
  value: any
60
59
  pos?: ITokenPosition
61
60
  }
62
61
 
63
- const validateSymbol = (val: Symbol) => {
62
+ const validateSymbol = (val: TypeSymbol) => {
64
63
  if (!val.type) {
65
64
  throw new PredicateError('Internal error')
66
65
  }
@@ -76,7 +75,7 @@ const validateSymbol = (val: Symbol) => {
76
75
  }
77
76
  }
78
77
 
79
- const resolveSymbol = (val: Symbol, vars: VariableMap): any => {
78
+ const resolveSymbol = (val: TypeSymbol, vars: VariableMap): any => {
80
79
  if (val.type === 'var') {
81
80
  if (!(val.value in vars)) {
82
81
  throw new PredicateError(`Missing parameter value for ${val.value}`)
@@ -87,7 +86,7 @@ const resolveSymbol = (val: Symbol, vars: VariableMap): any => {
87
86
  return val.value
88
87
  }
89
88
 
90
- const resolveValue = (obj: any, val: Symbol): any => {
89
+ const resolveValue = (obj: any, val: TypeSymbol): any => {
91
90
  if (val.type !== 'identifier') {
92
91
  throw new PredicateError('Internal error')
93
92
  }
@@ -95,8 +94,8 @@ const resolveValue = (obj: any, val: Symbol): any => {
95
94
  if (!(val.value in obj)) {
96
95
  if (Array.isArray(obj)) {
97
96
  return Object.values(obj)
98
- .filter(v => val.value in v)
99
- .map(v => v[val.value])
97
+ .filter((v) => val.value in v)
98
+ .map((v) => v[val.value])
100
99
  }
101
100
  throw new PredicateError(`The field '${val.value}' does not exist.`)
102
101
  }
@@ -104,8 +103,8 @@ const resolveValue = (obj: any, val: Symbol): any => {
104
103
  return obj[val.value]
105
104
  }
106
105
 
107
- const getLexer = (value: string) => {
108
- return new perplex(value)
106
+ const getLexer = (value: string) =>
107
+ new perplex(value)
109
108
 
110
109
  .token('AND', /and(?![-_a-z0-9]+)/i)
111
110
  .token('OR', /or(?![-_a-z0-9]+)/i)
@@ -140,7 +139,6 @@ const getLexer = (value: string) => {
140
139
  .token('=', '=')
141
140
  .token('"', '"')
142
141
  .token('WS', /\s+/, true) // skip
143
- }
144
142
 
145
143
  /**
146
144
  * This function converts a query expression in to a callable which returns a
@@ -153,74 +151,82 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
153
151
  const lexer = getLexer(predicate)
154
152
  const parser = new Parser(lexer)
155
153
  .builder()
156
- .nud('IDENTIFIER', 100, t => {
157
- return {
158
- type: 'identifier',
159
- value: t.token.match,
160
- pos: t.token.strpos(),
161
- } as Symbol
162
- })
163
- .nud('BOOLEAN', 1, t => {
164
- return {
165
- type: 'boolean',
166
- value: t.token.match === 'true' ? true : false,
167
- pos: t.token.strpos(),
168
- } as Symbol
169
- })
170
- .nud('VARIABLE', 100, t => {
171
- return {
172
- type: 'var',
173
- // @ts-ignore
174
- value: t.token.groups[1],
175
- pos: t.token.strpos(),
176
- } as Symbol
177
- })
178
- .nud('STRING', 100, t => {
179
- return {
180
- type: 'string',
181
- // @ts-ignore
182
- value: t.token.groups[1],
183
- pos: t.token.strpos(),
184
- } as Symbol
185
- })
186
- .nud('INT', 1, t => {
187
- return {
188
- type: 'int',
189
- value: parseInt(t.token.match, 10),
190
- pos: t.token.strpos(),
191
- } as Symbol
192
- })
193
- .nud('FLOAT', 1, t => {
194
- return {
195
- type: 'float',
196
- value: parseFloat(t.token.match),
197
- pos: t.token.strpos(),
198
- } as Symbol
199
- })
154
+ .nud(
155
+ 'IDENTIFIER',
156
+ 100,
157
+ (t) =>
158
+ ({
159
+ type: 'identifier',
160
+ value: t.token.match,
161
+ pos: t.token.strpos(),
162
+ } as TypeSymbol)
163
+ )
164
+ .nud(
165
+ 'BOOLEAN',
166
+ 1,
167
+ (t) =>
168
+ ({
169
+ type: 'boolean',
170
+ value: t.token.match === 'true' ? true : false,
171
+ pos: t.token.strpos(),
172
+ } as TypeSymbol)
173
+ )
174
+ .nud(
175
+ 'VARIABLE',
176
+ 100,
177
+ (t) =>
178
+ ({
179
+ type: 'var',
180
+ // @ts-ignore
181
+ value: t.token.groups[1],
182
+ pos: t.token.strpos(),
183
+ } as TypeSymbol)
184
+ )
185
+ .nud(
186
+ 'STRING',
187
+ 100,
188
+ (t) =>
189
+ ({
190
+ type: 'string',
191
+ // @ts-ignore
192
+ value: t.token.groups[1],
193
+ pos: t.token.strpos(),
194
+ } as TypeSymbol)
195
+ )
196
+ .nud(
197
+ 'INT',
198
+ 1,
199
+ (t) =>
200
+ ({
201
+ type: 'int',
202
+ value: parseInt(t.token.match, 10),
203
+ pos: t.token.strpos(),
204
+ } as TypeSymbol)
205
+ )
206
+ .nud(
207
+ 'FLOAT',
208
+ 1,
209
+ (t) =>
210
+ ({
211
+ type: 'float',
212
+ value: parseFloat(t.token.match),
213
+ pos: t.token.strpos(),
214
+ } as TypeSymbol)
215
+ )
200
216
  .nud('NOT', 100, ({ bp }) => {
201
217
  const expr = parser.parse({ terminals: [bp - 1] })
202
- return (obj: any) => {
203
- return !expr(obj)
204
- }
205
- })
206
- .nud('EMPTY', 10, ({ bp }) => {
207
- return 'empty'
208
- })
209
- .nud('DEFINED', 10, ({ bp }) => {
210
- return 'defined'
218
+ return (obj: any) => !expr(obj)
211
219
  })
220
+ .nud('EMPTY', 10, ({ bp }) => 'empty')
221
+ .nud('DEFINED', 10, ({ bp }) => 'defined')
212
222
 
213
223
  .led('AND', 5, ({ left, bp }) => {
214
224
  const expr = parser.parse({ terminals: [bp - 1] })
215
- return (obj: any) => {
216
- return left(obj) && expr(obj)
217
- }
225
+ return (obj: any) => left(obj) && expr(obj)
218
226
  })
219
227
  .led('OR', 5, ({ left, token, bp }) => {
220
228
  const expr = parser.parse({ terminals: [bp - 1] })
221
- return (obj: any, vars: object) => {
222
- return left(obj, vars) || expr(obj, vars)
223
- }
229
+ return (obj: any, vars: object) => left(obj, vars) || expr(obj, vars)
224
230
  })
225
231
  .led('COMMA', 1, ({ left, token, bp }) => {
226
232
  const expr: any = parser.parse({ terminals: [bp - 1] })
@@ -230,7 +236,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
230
236
  return [left, expr]
231
237
  }
232
238
  })
233
- .nud('(', 100, t => {
239
+ .nud('(', 100, (t) => {
234
240
  const expr: any = parser.parse({ terminals: [')'] })
235
241
  return expr
236
242
  })
@@ -254,7 +260,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
254
260
  const resolvedValue = resolveValue(obj, left)
255
261
  const resolvedSymbol = resolveSymbol(expr, vars)
256
262
  if (Array.isArray(resolvedValue)) {
257
- return !!resolvedValue.some(elem => elem === resolvedSymbol)
263
+ return !!resolvedValue.some((elem) => elem === resolvedSymbol)
258
264
  }
259
265
  return resolvedValue === resolvedSymbol
260
266
  }
@@ -262,41 +268,36 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
262
268
  .led('!=', 20, ({ left, bp }) => {
263
269
  const expr = parser.parse({ terminals: [bp - 1] })
264
270
  validateSymbol(expr)
265
- return (obj: any, vars: VariableMap) => {
266
- return resolveValue(obj, left) !== resolveSymbol(expr, vars)
267
- }
271
+ return (obj: any, vars: VariableMap) =>
272
+ resolveValue(obj, left) !== resolveSymbol(expr, vars)
268
273
  })
269
274
  .led('>', 20, ({ left, bp }) => {
270
275
  const expr = parser.parse({ terminals: [bp - 1] })
271
276
  validateSymbol(expr)
272
277
 
273
- return (obj: any, vars: object) => {
274
- return resolveValue(obj, left) > resolveSymbol(expr, vars)
275
- }
278
+ return (obj: any, vars: object) =>
279
+ resolveValue(obj, left) > resolveSymbol(expr, vars)
276
280
  })
277
281
  .led('>=', 20, ({ left, bp }) => {
278
282
  const expr = parser.parse({ terminals: [bp - 1] })
279
283
  validateSymbol(expr)
280
284
 
281
- return (obj: any, vars: object) => {
282
- return resolveValue(obj, left) >= resolveSymbol(expr, vars)
283
- }
285
+ return (obj: any, vars: object) =>
286
+ resolveValue(obj, left) >= resolveSymbol(expr, vars)
284
287
  })
285
288
  .led('<', 20, ({ left, bp }) => {
286
289
  const expr = parser.parse({ terminals: [bp - 1] })
287
290
  validateSymbol(expr)
288
291
 
289
- return (obj: any, vars: object) => {
290
- return resolveValue(obj, left) < resolveSymbol(expr, vars)
291
- }
292
+ return (obj: any, vars: object) =>
293
+ resolveValue(obj, left) < resolveSymbol(expr, vars)
292
294
  })
293
295
  .led('<=', 20, ({ left, bp }) => {
294
296
  const expr = parser.parse({ terminals: [bp - 1] })
295
297
  validateSymbol(expr)
296
298
 
297
- return (obj: any, vars: object) => {
298
- return resolveValue(obj, left) <= resolveSymbol(expr, vars)
299
- }
299
+ return (obj: any, vars: object) =>
300
+ resolveValue(obj, left) <= resolveSymbol(expr, vars)
300
301
  })
301
302
  .led('IS', 20, ({ left, bp }) => {
302
303
  let invert = false
@@ -350,7 +351,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
350
351
  symbols = [expr]
351
352
  }
352
353
 
353
- const inValues = symbols.map((item: Symbol) =>
354
+ const inValues = symbols.map((item: TypeSymbol) =>
354
355
  resolveSymbol(item, vars)
355
356
  )
356
357
  return inValues.includes(resolveValue(obj, left))
@@ -419,7 +420,7 @@ const generateMatchFunc = (predicate: string): MatchFunc => {
419
420
  )
420
421
  }
421
422
 
422
- const array = expr.map((item: Symbol) => resolveSymbol(item, vars))
423
+ const array = expr.map((item: TypeSymbol) => resolveSymbol(item, vars))
423
424
  if (keyword.type === 'ALL') {
424
425
  return array.every((item: any) => value.includes(item))
425
426
  } else {