@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.
Files changed (95) hide show
  1. package/README.md +8 -0
  2. package/dist/index.d.ts +18 -17
  3. package/dist/index.global.js +1751 -1664
  4. package/dist/index.global.js.map +1 -1
  5. package/dist/index.js +1773 -1684
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +1966 -1877
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +28 -20
  10. package/src/constants.ts +4 -2
  11. package/src/ctMock.ts +19 -84
  12. package/src/helpers.ts +9 -10
  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.test.ts +16 -0
  17. package/src/lib/predicateParser.ts +94 -86
  18. package/src/lib/projectionSearchFilter.test.ts +28 -36
  19. package/src/lib/projectionSearchFilter.ts +86 -102
  20. package/src/oauth/store.ts +3 -3
  21. package/src/priceSelector.test.ts +18 -35
  22. package/src/priceSelector.ts +6 -9
  23. package/src/product-projection-search.ts +51 -57
  24. package/src/repositories/abstract.ts +85 -41
  25. package/src/repositories/cart-discount.ts +1 -1
  26. package/src/repositories/cart.ts +36 -31
  27. package/src/repositories/category.ts +17 -19
  28. package/src/repositories/channel.ts +1 -1
  29. package/src/repositories/custom-object.ts +35 -22
  30. package/src/repositories/customer-group.ts +1 -1
  31. package/src/repositories/customer.ts +39 -1
  32. package/src/repositories/discount-code.ts +1 -1
  33. package/src/repositories/errors.ts +9 -11
  34. package/src/repositories/extension.ts +13 -11
  35. package/src/repositories/helpers.ts +8 -13
  36. package/src/repositories/index.ts +59 -0
  37. package/src/repositories/inventory-entry.ts +1 -1
  38. package/src/repositories/order.ts +6 -6
  39. package/src/repositories/payment.ts +3 -3
  40. package/src/repositories/product-discount.ts +1 -1
  41. package/src/repositories/product-projection.ts +1 -0
  42. package/src/repositories/product-type.ts +29 -34
  43. package/src/repositories/product.ts +124 -80
  44. package/src/repositories/project.ts +10 -27
  45. package/src/repositories/shipping-method.ts +15 -17
  46. package/src/repositories/shopping-list.ts +2 -2
  47. package/src/repositories/state.ts +9 -9
  48. package/src/repositories/store.ts +2 -2
  49. package/src/repositories/subscription.ts +1 -1
  50. package/src/repositories/tax-category.ts +4 -4
  51. package/src/repositories/type.ts +12 -14
  52. package/src/repositories/zone.ts +5 -6
  53. package/src/server.ts +5 -0
  54. package/src/services/abstract.ts +44 -11
  55. package/src/services/cart-discount.ts +2 -3
  56. package/src/services/cart.test.ts +8 -10
  57. package/src/services/cart.ts +8 -11
  58. package/src/services/category.test.ts +1 -2
  59. package/src/services/category.ts +2 -3
  60. package/src/services/channel.ts +2 -3
  61. package/src/services/custom-object.test.ts +5 -5
  62. package/src/services/custom-object.ts +2 -3
  63. package/src/services/customer-group.ts +2 -3
  64. package/src/services/customer.test.ts +136 -0
  65. package/src/services/customer.ts +2 -3
  66. package/src/services/discount-code.ts +2 -3
  67. package/src/services/extension.ts +2 -3
  68. package/src/services/index.ts +74 -0
  69. package/src/services/inventory-entry.test.ts +8 -12
  70. package/src/services/inventory-entry.ts +2 -3
  71. package/src/services/my-cart.ts +3 -4
  72. package/src/services/my-customer.ts +2 -3
  73. package/src/services/my-order.ts +3 -4
  74. package/src/services/my-payment.ts +2 -3
  75. package/src/services/order.test.ts +4 -6
  76. package/src/services/order.ts +2 -3
  77. package/src/services/payment.ts +2 -3
  78. package/src/services/product-discount.ts +2 -3
  79. package/src/services/product-projection.test.ts +76 -8
  80. package/src/services/product-projection.ts +2 -3
  81. package/src/services/product-type.ts +2 -3
  82. package/src/services/product.test.ts +199 -89
  83. package/src/services/product.ts +2 -3
  84. package/src/services/project.ts +3 -3
  85. package/src/services/shipping-method.ts +2 -3
  86. package/src/services/shopping-list.ts +2 -3
  87. package/src/services/state.ts +2 -3
  88. package/src/services/store.test.ts +11 -2
  89. package/src/services/store.ts +2 -3
  90. package/src/services/subscription.ts +2 -3
  91. package/src/services/tax-category.ts +2 -3
  92. package/src/services/type.ts +2 -3
  93. package/src/services/zone.ts +2 -3
  94. package/src/storage.ts +23 -30
  95. package/src/types.ts +46 -6
package/package.json CHANGED
@@ -1,7 +1,10 @@
1
1
  {
2
- "version": "0.9.0",
2
+ "name": "@labdigital/commercetools-mock",
3
+ "author": "Michael van Tellingen",
4
+ "version": "0.10.0",
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,17 +17,30 @@
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
+ "uuid": "^8.3.2"
43
+ },
28
44
  "devDependencies": {
29
45
  "@babel/preset-env": "^7.18.9",
30
46
  "@babel/preset-typescript": "^7.18.6",
@@ -40,13 +56,17 @@
40
56
  "@types/qs": "^6.9.7",
41
57
  "@types/supertest": "^2.0.11",
42
58
  "@types/uuid": "^8.3.4",
59
+ "@typescript-eslint/eslint-plugin": "^5.39.0",
60
+ "@typescript-eslint/parser": "^5.39.0",
43
61
  "esbuild": "^0.14.50",
44
62
  "esbuild-register": "^3.3.1",
45
63
  "eslint": "^8.20.0",
64
+ "eslint-plugin-unused-imports": "^2.0.0",
46
65
  "got": "^11.8.3",
47
66
  "husky": "^7.0.4",
48
67
  "jest": "^28.1.3",
49
68
  "nodemon": "^2.0.15",
69
+ "prettier": "^2.7.1",
50
70
  "timekeeper": "^2.2.0",
51
71
  "ts-node": "^10.4.0",
52
72
  "tsc": "^2.0.4",
@@ -54,27 +74,15 @@
54
74
  "tsup": "^6.2.0",
55
75
  "typescript": "^4.7.4"
56
76
  },
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
77
  "peerDependencies": {
72
78
  "@commercetools/platform-sdk": "^2.4.1"
73
79
  },
74
80
  "scripts": {
75
81
  "start": "nodemon --watch src --exec 'node -r esbuild-register' src/server.ts",
76
82
  "build": "tsup",
83
+ "build:server": "esbuild src/server.ts --bundle --outfile=dist/server.js --platform=node",
84
+ "check": "eslint src && tsc",
77
85
  "test": "jest test --coverage",
78
- "lint": "eslint"
86
+ "lint": "eslint src"
79
87
  }
80
88
  }
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
@@ -3,7 +3,7 @@ import express, { NextFunction, Request, Response } from 'express'
3
3
  import supertest from 'supertest'
4
4
  import morgan from 'morgan'
5
5
  import { AbstractStorage, InMemoryStorage } from './storage'
6
- import { Services } from './types'
6
+ import { Repositories, Services } from './types'
7
7
  import { CommercetoolsError } from './exceptions'
8
8
  import { OAuth2Server } from './oauth/server'
9
9
  import { ProjectAPI } from './projectAPI'
@@ -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 } from './repositories'
16
+ import { createServices } from './services'
17
+ import { ProjectRepository } from 'repositories/project'
43
18
 
44
19
  export type CommercetoolsMockOptions = {
45
20
  validateCredentials: boolean
@@ -72,11 +47,13 @@ export class CommercetoolsMock {
72
47
  api: nock.Scope | undefined
73
48
  } = { auth: undefined, api: undefined }
74
49
  private _services: Services
50
+ private _repositories: Repositories
75
51
  private _projectService?: ProjectService
76
52
 
77
53
  constructor(options: Partial<CommercetoolsMockOptions> = {}) {
78
54
  this.options = { ...DEFAULT_OPTIONS, ...options }
79
55
  this._services = {}
56
+ this._repositories = {}
80
57
  this._projectService = undefined
81
58
 
82
59
  this._storage = new InMemoryStorage()
@@ -118,10 +95,9 @@ export class CommercetoolsMock {
118
95
  )
119
96
  }
120
97
 
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}`)
98
+ runServer(port = 3000, options?: AppOptions) {
99
+ const server = this.app.listen(port, () => {
100
+ console.info(`Mock server listening at http://localhost:${port}`)
125
101
  })
126
102
  server.keepAliveTimeout = 60 * 1000
127
103
  }
@@ -150,53 +126,12 @@ export class CommercetoolsMock {
150
126
  app.use('/:projectKey/in-store/key=:storeKey', projectRouter)
151
127
  }
152
128
 
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
- }
129
+ this._repositories = createRepositories(this._storage)
130
+ this._projectService = new ProjectService(
131
+ projectRouter,
132
+ this._repositories.project as ProjectRepository
133
+ )
134
+ this._services = createServices(projectRouter, this._repositories)
200
135
 
201
136
  app.use((err: Error, req: Request, resp: Response, next: NextFunction) => {
202
137
  if (err instanceof CommercetoolsError) {
@@ -222,14 +157,14 @@ export class CommercetoolsMock {
222
157
  this._nockScopes.api = nock(this.options.apiHost)
223
158
  .persist()
224
159
  .get(/.*/)
225
- .reply(async function(uri) {
160
+ .reply(async function (uri) {
226
161
  const response = await supertest(app)
227
162
  .get(uri)
228
163
  .set(copyHeaders(this.req.headers))
229
164
  return [response.status, response.body]
230
165
  })
231
166
  .post(/.*/)
232
- .reply(async function(uri, body) {
167
+ .reply(async function (uri, body) {
233
168
  const response = await supertest(app)
234
169
  .post(uri)
235
170
  .set(copyHeaders(this.req.headers))
@@ -237,7 +172,7 @@ export class CommercetoolsMock {
237
172
  return [response.status, response.body]
238
173
  })
239
174
  .delete(/.*/)
240
- .reply(async function(uri, body) {
175
+ .reply(async function (uri, body) {
241
176
  const response = await supertest(app)
242
177
  .delete(uri)
243
178
  .set(copyHeaders(this.req.headers))
@@ -252,7 +187,7 @@ export class CommercetoolsMock {
252
187
  this._nockScopes.auth = nock(this.options.authHost)
253
188
  .persist()
254
189
  .post(/^\/oauth\/.*/)
255
- .reply(async function(uri, body) {
190
+ .reply(async function (uri, body) {
256
191
  const response = await supertest(app)
257
192
  .post(uri + '?' + body)
258
193
  .set(copyHeaders(this.req.headers))
package/src/helpers.ts CHANGED
@@ -1,15 +1,12 @@
1
1
  import { v4 as uuidv4 } from 'uuid'
2
2
  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
- }
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()
@@ -8,10 +8,12 @@ describe('Predicate filter', () => {
8
8
  arrayProperty: ['foo', 'bar', 'nar'],
9
9
  notDefined: undefined,
10
10
  emptyArrayProperty: [],
11
+ booleanProperty: true,
11
12
  nested: {
12
13
  numberProperty: 1234,
13
14
  objectProperty: {
14
15
  stringProperty: 'foobar',
16
+ booleanProperty: true,
15
17
  },
16
18
  },
17
19
 
@@ -31,6 +33,13 @@ describe('Predicate filter', () => {
31
33
  expect(match(`stringProperty=:val`, { val: 'foobar' })).toBeTruthy()
32
34
  })
33
35
 
36
+ test('booleanProperty = true', async () => {
37
+ expect(match(`booleanProperty != true`)).toBeFalsy()
38
+ expect(match(`booleanProperty = true`)).toBeTruthy()
39
+
40
+ expect(match(`booleanProperty=:val`, { val: true })).toBeTruthy()
41
+ })
42
+
34
43
  test('stringProperty matches ignore case "foobar"', async () => {
35
44
  expect(match(`stringProperty="FOObar"`)).toBeFalsy()
36
45
  expect(match(`stringProperty matches ignore case "FOObar"`)).toBeTruthy()
@@ -168,6 +177,13 @@ describe('Predicate filter', () => {
168
177
  ).toBeTruthy()
169
178
  })
170
179
 
180
+ test('nested attribute access', async () => {
181
+ expect(match(`nested(objectProperty(booleanProperty != true))`)).toBeFalsy()
182
+ expect(
183
+ match(`nested(objectProperty(booleanProperty != false))`)
184
+ ).toBeTruthy()
185
+ })
186
+
171
187
  test('lexer confusion', async () => {
172
188
  expect(() => match(`orSomething="foobar"`)).toThrow(PredicateError)
173
189
  expect(() => match(`orSomething="foobar"`)).toThrow(