@labdigital/commercetools-mock 2.66.0 → 3.0.0-beta.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 (281) hide show
  1. package/README.md +31 -8
  2. package/dist/abstract-BKFcva6S.mjs +1044 -0
  3. package/dist/abstract-BKFcva6S.mjs.map +1 -0
  4. package/dist/config-BcNSzPZz.d.mts +1718 -0
  5. package/dist/index.d.mts +50 -1633
  6. package/dist/index.mjs +3769 -2653
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/storage/sqlite.d.mts +59 -0
  9. package/dist/storage/sqlite.mjs +234 -0
  10. package/dist/storage/sqlite.mjs.map +1 -0
  11. package/package.json +26 -29
  12. package/src/ctMock.ts +125 -136
  13. package/src/helpers.ts +14 -6
  14. package/src/index.ts +5 -0
  15. package/src/lib/masking.ts +4 -5
  16. package/src/lib/product-review-statistics.test.ts +257 -294
  17. package/src/lib/review-statistics.ts +17 -4
  18. package/src/oauth/helpers.ts +7 -4
  19. package/src/oauth/server.test.ts +102 -62
  20. package/src/oauth/server.ts +215 -213
  21. package/src/oauth/store.ts +20 -6
  22. package/src/orderSearch.ts +3 -3
  23. package/src/product-projection-search.ts +38 -20
  24. package/src/product-search-availability.test.ts +31 -52
  25. package/src/product-search.ts +19 -10
  26. package/src/projectAPI.ts +6 -22
  27. package/src/repositories/abstract.ts +182 -48
  28. package/src/repositories/as-associate.test.ts +19 -19
  29. package/src/repositories/associate-role.ts +12 -23
  30. package/src/repositories/attribute-group.test.ts +23 -23
  31. package/src/repositories/attribute-group.ts +6 -4
  32. package/src/repositories/business-unit.test.ts +63 -57
  33. package/src/repositories/business-unit.ts +107 -55
  34. package/src/repositories/cart/actions.ts +96 -65
  35. package/src/repositories/cart/helpers.ts +15 -11
  36. package/src/repositories/cart/index.test.ts +136 -30
  37. package/src/repositories/cart/index.ts +76 -59
  38. package/src/repositories/cart-discount/actions.ts +12 -44
  39. package/src/repositories/cart-discount/index.ts +20 -8
  40. package/src/repositories/category/actions.ts +27 -27
  41. package/src/repositories/category/index.test.ts +13 -9
  42. package/src/repositories/category/index.ts +40 -23
  43. package/src/repositories/channel.test.ts +53 -51
  44. package/src/repositories/channel.ts +12 -22
  45. package/src/repositories/custom-object.ts +34 -25
  46. package/src/repositories/customer/actions.ts +47 -25
  47. package/src/repositories/customer/index.test.ts +11 -11
  48. package/src/repositories/customer/index.ts +65 -35
  49. package/src/repositories/customer-group.test.ts +44 -42
  50. package/src/repositories/customer-group.ts +12 -22
  51. package/src/repositories/discount-code/actions.ts +3 -19
  52. package/src/repositories/discount-code/index.ts +9 -4
  53. package/src/repositories/discount-group/index.ts +8 -3
  54. package/src/repositories/extension.test.ts +27 -27
  55. package/src/repositories/extension.ts +10 -5
  56. package/src/repositories/helpers.ts +126 -47
  57. package/src/repositories/inventory-entry/actions.ts +3 -24
  58. package/src/repositories/inventory-entry/index.ts +19 -11
  59. package/src/repositories/my-customer.ts +13 -12
  60. package/src/repositories/my-order.ts +5 -2
  61. package/src/repositories/order/actions.ts +84 -56
  62. package/src/repositories/order/index.test.ts +36 -31
  63. package/src/repositories/order/index.ts +83 -49
  64. package/src/repositories/order-edit.ts +8 -3
  65. package/src/repositories/payment/actions.ts +64 -44
  66. package/src/repositories/payment/helpers.ts +3 -3
  67. package/src/repositories/payment/index.ts +28 -12
  68. package/src/repositories/product/actions.ts +133 -98
  69. package/src/repositories/product/helpers.ts +29 -16
  70. package/src/repositories/product/index.ts +42 -25
  71. package/src/repositories/product-discount.ts +6 -4
  72. package/src/repositories/product-projection.ts +41 -21
  73. package/src/repositories/product-selection.ts +8 -15
  74. package/src/repositories/product-tailoring.ts +22 -3
  75. package/src/repositories/product-type.ts +45 -4
  76. package/src/repositories/project.ts +57 -13
  77. package/src/repositories/quote/actions.ts +5 -28
  78. package/src/repositories/quote/index.ts +29 -6
  79. package/src/repositories/quote-request/actions.ts +5 -28
  80. package/src/repositories/quote-request/index.test.ts +3 -3
  81. package/src/repositories/quote-request/index.ts +31 -11
  82. package/src/repositories/quote-staged/actions.ts +5 -28
  83. package/src/repositories/quote-staged/index.ts +22 -8
  84. package/src/repositories/recurrence-policy/index.ts +6 -4
  85. package/src/repositories/recurring-order/actions.ts +7 -32
  86. package/src/repositories/recurring-order/index.ts +8 -6
  87. package/src/repositories/review.test.ts +147 -142
  88. package/src/repositories/review.ts +31 -37
  89. package/src/repositories/shipping-method/actions.ts +11 -28
  90. package/src/repositories/shipping-method/index.ts +26 -15
  91. package/src/repositories/shopping-list/actions.ts +21 -31
  92. package/src/repositories/shopping-list/index.ts +44 -22
  93. package/src/repositories/standalone-price.ts +6 -4
  94. package/src/repositories/state.ts +15 -9
  95. package/src/repositories/store.ts +21 -32
  96. package/src/repositories/subscription.test.ts +22 -22
  97. package/src/repositories/subscription.ts +8 -3
  98. package/src/repositories/tax-category/index.ts +8 -3
  99. package/src/repositories/type/actions.ts +21 -3
  100. package/src/repositories/type/index.ts +5 -3
  101. package/src/repositories/zone.test.ts +112 -77
  102. package/src/repositories/zone.ts +5 -3
  103. package/src/schemas/generated/associate-role.ts +13 -0
  104. package/src/schemas/generated/attribute-group.ts +12 -0
  105. package/src/schemas/generated/business-unit.ts +38 -0
  106. package/src/schemas/generated/cart-discount.ts +33 -0
  107. package/src/schemas/generated/cart.ts +61 -0
  108. package/src/schemas/generated/category.ts +25 -0
  109. package/src/schemas/generated/channel.ts +21 -0
  110. package/src/schemas/generated/common.ts +1372 -0
  111. package/src/schemas/generated/custom-object.ts +11 -0
  112. package/src/schemas/generated/customer-group.ts +11 -0
  113. package/src/schemas/generated/customer.ts +47 -0
  114. package/src/schemas/generated/discount-code.ts +25 -0
  115. package/src/schemas/generated/discount-group.ts +13 -0
  116. package/src/schemas/generated/extension.ts +15 -0
  117. package/src/schemas/generated/index.ts +42 -0
  118. package/src/schemas/generated/inventory-entry.ts +20 -0
  119. package/src/schemas/generated/my-quote-request.ts +10 -0
  120. package/src/schemas/generated/order-edit.ts +18 -0
  121. package/src/schemas/generated/order-from-cart.ts +25 -0
  122. package/src/schemas/generated/payment.ts +30 -0
  123. package/src/schemas/generated/product-discount.ts +20 -0
  124. package/src/schemas/generated/product-selection.ts +18 -0
  125. package/src/schemas/generated/product-tailoring.ts +26 -0
  126. package/src/schemas/generated/product-type.ts +12 -0
  127. package/src/schemas/generated/product.ts +37 -0
  128. package/src/schemas/generated/quote-request.ts +19 -0
  129. package/src/schemas/generated/quote.ts +18 -0
  130. package/src/schemas/generated/recurrence-policy.ts +15 -0
  131. package/src/schemas/generated/recurring-order.ts +19 -0
  132. package/src/schemas/generated/review.ts +24 -0
  133. package/src/schemas/generated/shipping-method.ts +24 -0
  134. package/src/schemas/generated/shopping-list.ts +28 -0
  135. package/src/schemas/generated/staged-quote.ts +18 -0
  136. package/src/schemas/generated/standalone-price.ts +32 -0
  137. package/src/schemas/generated/state.ts +20 -0
  138. package/src/schemas/generated/store.ts +23 -0
  139. package/src/schemas/generated/subscription.ts +20 -0
  140. package/src/schemas/generated/tax-category.ts +12 -0
  141. package/src/schemas/generated/type.ts +17 -0
  142. package/src/schemas/generated/zone.ts +12 -0
  143. package/src/schemas/update-request.ts +3 -5
  144. package/src/server.ts +32 -4
  145. package/src/services/abstract.ts +207 -101
  146. package/src/services/as-associate-cart.test.ts +28 -36
  147. package/src/services/as-associate-cart.ts +15 -12
  148. package/src/services/as-associate-order.test.ts +33 -40
  149. package/src/services/as-associate-order.ts +15 -12
  150. package/src/services/as-associate-quote-request.ts +15 -12
  151. package/src/services/as-associate-shopping-list.test.ts +25 -35
  152. package/src/services/as-associate-shopping-list.ts +15 -12
  153. package/src/services/as-associate.test.ts +21 -15
  154. package/src/services/as-associate.ts +23 -22
  155. package/src/services/associate-roles.test.ts +16 -22
  156. package/src/services/associate-roles.ts +2 -2
  157. package/src/services/attribute-group.test.ts +40 -44
  158. package/src/services/attribute-group.ts +2 -2
  159. package/src/services/business-units.test.ts +227 -163
  160. package/src/services/business-units.ts +2 -2
  161. package/src/services/cart-discount.test.ts +253 -187
  162. package/src/services/cart-discount.ts +2 -2
  163. package/src/services/cart.test.ts +833 -832
  164. package/src/services/cart.ts +31 -12
  165. package/src/services/category.test.ts +208 -130
  166. package/src/services/category.ts +2 -2
  167. package/src/services/channel.test.ts +39 -44
  168. package/src/services/channel.ts +2 -2
  169. package/src/services/custom-object.test.ts +103 -79
  170. package/src/services/custom-object.ts +106 -38
  171. package/src/services/customer-group.test.ts +39 -44
  172. package/src/services/customer-group.ts +2 -2
  173. package/src/services/customer.test.ts +357 -292
  174. package/src/services/customer.ts +70 -23
  175. package/src/services/discount-code.test.ts +57 -68
  176. package/src/services/discount-code.ts +2 -2
  177. package/src/services/discount-group.test.ts +111 -134
  178. package/src/services/discount-group.ts +2 -2
  179. package/src/services/draft-validation.test.ts +255 -0
  180. package/src/services/extension.test.ts +39 -44
  181. package/src/services/extension.ts +2 -2
  182. package/src/services/inventory-entry.test.ts +106 -87
  183. package/src/services/inventory-entry.ts +2 -2
  184. package/src/services/my-business-unit.test.ts +82 -112
  185. package/src/services/my-business-unit.ts +25 -19
  186. package/src/services/my-cart.test.ts +46 -41
  187. package/src/services/my-cart.ts +32 -28
  188. package/src/services/my-customer.test.ts +153 -88
  189. package/src/services/my-customer.ts +130 -61
  190. package/src/services/my-order.ts +15 -12
  191. package/src/services/my-payment.test.ts +30 -24
  192. package/src/services/my-payment.ts +2 -2
  193. package/src/services/my-shopping-list.ts +2 -2
  194. package/src/services/order.test.ts +332 -276
  195. package/src/services/order.ts +45 -27
  196. package/src/services/payment.test.ts +31 -29
  197. package/src/services/payment.ts +2 -2
  198. package/src/services/product-discount.test.ts +39 -46
  199. package/src/services/product-discount.ts +2 -2
  200. package/src/services/product-projection.test.ts +176 -166
  201. package/src/services/product-projection.ts +31 -15
  202. package/src/services/product-selection.test.ts +17 -9
  203. package/src/services/product-selection.ts +2 -2
  204. package/src/services/product-type.test.ts +80 -21
  205. package/src/services/product-type.ts +2 -2
  206. package/src/services/product.test.ts +569 -534
  207. package/src/services/product.ts +14 -7
  208. package/src/services/project.test.ts +22 -12
  209. package/src/services/project.ts +28 -13
  210. package/src/services/quote-request.test.ts +36 -39
  211. package/src/services/quote-request.ts +2 -2
  212. package/src/services/quote-staged.ts +2 -2
  213. package/src/services/quote.ts +2 -2
  214. package/src/services/recurrence-policy.test.ts +114 -139
  215. package/src/services/recurrence-policy.ts +2 -2
  216. package/src/services/recurring-order.test.ts +149 -194
  217. package/src/services/recurring-order.ts +2 -2
  218. package/src/services/reviews.test.ts +127 -106
  219. package/src/services/reviews.ts +2 -2
  220. package/src/services/shipping-method.test.ts +96 -125
  221. package/src/services/shipping-method.ts +24 -12
  222. package/src/services/shopping-list.test.ts +183 -141
  223. package/src/services/shopping-list.ts +2 -2
  224. package/src/services/standalone-price.test.ts +60 -46
  225. package/src/services/standalone-price.ts +2 -2
  226. package/src/services/state.test.ts +20 -25
  227. package/src/services/state.ts +2 -2
  228. package/src/services/store.test.ts +26 -45
  229. package/src/services/store.ts +2 -2
  230. package/src/services/subscription.test.ts +39 -44
  231. package/src/services/subscription.ts +2 -2
  232. package/src/services/tax-category.test.ts +33 -36
  233. package/src/services/tax-category.ts +2 -2
  234. package/src/services/type.test.ts +45 -44
  235. package/src/services/type.ts +2 -2
  236. package/src/services/zone.test.ts +40 -44
  237. package/src/services/zone.ts +2 -2
  238. package/src/shipping.ts +41 -11
  239. package/src/storage/abstract.ts +248 -17
  240. package/src/storage/in-memory.ts +147 -290
  241. package/src/storage/sqlite.ts +429 -0
  242. package/src/storage/storage-map.ts +75 -0
  243. package/src/storage/storage.test-helpers.ts +97 -0
  244. package/src/storage/storage.test.ts +802 -0
  245. package/src/testing/associate-role.ts +28 -0
  246. package/src/testing/attribute-group.ts +27 -0
  247. package/src/testing/business-unit.ts +9 -8
  248. package/src/testing/cart-discount.ts +34 -0
  249. package/src/testing/cart.ts +20 -0
  250. package/src/testing/category.ts +25 -0
  251. package/src/testing/channel.ts +23 -0
  252. package/src/testing/custom-object.ts +27 -0
  253. package/src/testing/customer-group.ts +26 -0
  254. package/src/testing/customer.ts +36 -33
  255. package/src/testing/discount-code.ts +29 -0
  256. package/src/testing/discount-group.ts +27 -0
  257. package/src/testing/extension.ts +32 -0
  258. package/src/testing/index.ts +33 -0
  259. package/src/testing/inventory-entry.ts +26 -0
  260. package/src/testing/order.ts +27 -0
  261. package/src/testing/payment.ts +23 -0
  262. package/src/testing/product-discount.ts +33 -0
  263. package/src/testing/product-selection.ts +28 -0
  264. package/src/testing/product-type.ts +27 -0
  265. package/src/testing/product.ts +38 -0
  266. package/src/testing/quote-request.ts +29 -0
  267. package/src/testing/recurrence-policy.ts +33 -0
  268. package/src/testing/recurring-order.ts +32 -0
  269. package/src/testing/review.ts +24 -0
  270. package/src/testing/shipping-method.ts +31 -0
  271. package/src/testing/shopping-list.ts +25 -0
  272. package/src/testing/standalone-price.ts +31 -0
  273. package/src/testing/state.ts +21 -0
  274. package/src/testing/store.ts +26 -0
  275. package/src/testing/subscription.ts +38 -0
  276. package/src/testing/tax-category.ts +27 -0
  277. package/src/testing/type.ts +9 -6
  278. package/src/testing/zone.ts +22 -0
  279. package/src/validate.test.ts +122 -0
  280. package/src/validate.ts +78 -7
  281. package/src/.env +0 -0
@@ -10,12 +10,12 @@ describe("Customer repository", () => {
10
10
  const repository = new CustomerRepository(config);
11
11
 
12
12
  test("query by lowercaseEmail", async () => {
13
- const customer = repository.create(
13
+ const customer = await repository.create(
14
14
  { projectKey: "dummy" },
15
15
  { email: "my-customer-UPPERCASE@email.com" },
16
16
  );
17
17
 
18
- const result = repository.query(
18
+ const result = await repository.query(
19
19
  { projectKey: "dummy" },
20
20
  { where: [`lowercaseEmail = "my-customer-uppercase@email.com"`] },
21
21
  );
@@ -25,18 +25,18 @@ describe("Customer repository", () => {
25
25
  });
26
26
 
27
27
  test("updating lowercaseEmail", async () => {
28
- const customer = repository.create(
28
+ const customer = await repository.create(
29
29
  { projectKey: "dummy" },
30
30
  { email: "my-customer-UPPERCASE-v1@email.com" },
31
31
  );
32
32
 
33
- repository.saveUpdate({ projectKey: "dummy" }, customer.version, {
33
+ await repository.saveUpdate({ projectKey: "dummy" }, customer.version, {
34
34
  ...customer,
35
35
  email: "my-customer-UPPERCASE-v2@email.com",
36
36
  version: customer.version + 1,
37
37
  });
38
38
 
39
- const result = repository.query(
39
+ const result = await repository.query(
40
40
  { projectKey: "dummy" },
41
41
  { where: [`lowercaseEmail = "my-customer-uppercase-v2@email.com"`] },
42
42
  );
@@ -81,10 +81,10 @@ describe("Customer repository", () => {
81
81
  productSelections: [],
82
82
  };
83
83
 
84
- storage.add("dummy", "store", store1);
85
- storage.add("dummy", "store", store2);
84
+ await storage.add("dummy", "store", store1);
85
+ await storage.add("dummy", "store", store2);
86
86
 
87
- const result = repository.create(
87
+ const result = await repository.create(
88
88
  { projectKey: "dummy" },
89
89
  {
90
90
  email: "my-customer@email.com",
@@ -131,9 +131,9 @@ describe("Customer repository", () => {
131
131
  productSelections: [],
132
132
  };
133
133
 
134
- storage.add("dummy", "store", store1);
134
+ await storage.add("dummy", "store", store1);
135
135
 
136
- const result = repository.create(
136
+ const result = await repository.create(
137
137
  { projectKey: "dummy" },
138
138
  {
139
139
  email: "my-customer2@email.com",
@@ -155,7 +155,7 @@ describe("Customer repository", () => {
155
155
  });
156
156
 
157
157
  test("adding customer without linked stores", async () => {
158
- const result = repository.create(
158
+ const result = await repository.create(
159
159
  { projectKey: "dummy" },
160
160
  {
161
161
  email: "my-customer-without-stores@email.com",
@@ -8,6 +8,7 @@ import type {
8
8
  DuplicateFieldError,
9
9
  InvalidInputError,
10
10
  MyCustomerResetPassword,
11
+ RequiredFieldError,
11
12
  ResourceNotFoundError,
12
13
  Store,
13
14
  StoreKeyReference,
@@ -26,6 +27,7 @@ import {
26
27
  validateEmailVerifyToken,
27
28
  validatePasswordResetToken,
28
29
  } from "#src/lib/password.ts";
30
+ import { CustomerDraftSchema } from "#src/schemas/generated/customer.ts";
29
31
  import type { ResourceMap, ShallowWritable, Writable } from "#src/types.ts";
30
32
  import {
31
33
  AbstractResourceRepository,
@@ -38,13 +40,21 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
38
40
  constructor(config: Config) {
39
41
  super("customer", config);
40
42
  this.actions = new CustomerUpdateHandler(config.storage);
43
+ this.draftSchema = CustomerDraftSchema;
41
44
  }
42
45
 
43
- create(context: RepositoryContext, draft: CustomerDraft): Customer {
46
+ async create(
47
+ context: RepositoryContext,
48
+ draft: CustomerDraft,
49
+ ): Promise<Customer> {
44
50
  // Check uniqueness
45
- const results = this._storage.query(context.projectKey, this.getTypeId(), {
46
- where: [`lowercaseEmail="${draft.email.toLowerCase()}"`],
47
- });
51
+ const results = await this._storage.query(
52
+ context.projectKey,
53
+ this.getTypeId(),
54
+ {
55
+ where: [`lowercaseEmail="${draft.email.toLowerCase()}"`],
56
+ },
57
+ );
48
58
  if (results.count > 0) {
49
59
  throw new CommercetoolsError<any>({
50
60
  code: "CustomerAlreadyExists",
@@ -75,7 +85,14 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
75
85
  if (addressId < addresses.length) {
76
86
  const id = addresses[addressId].id;
77
87
  if (!id) {
78
- throw new Error("Address ID is missing");
88
+ throw new CommercetoolsError<RequiredFieldError>(
89
+ {
90
+ code: "RequiredField",
91
+ message: "Address ID is missing",
92
+ field: "addressId",
93
+ },
94
+ 400,
95
+ );
79
96
  }
80
97
  return id;
81
98
  }
@@ -112,14 +129,14 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
112
129
  let storesForCustomer: StoreKeyReference[] = [];
113
130
 
114
131
  if (draft.stores && draft.stores.length > 0) {
115
- storesForCustomer = this.storeReferenceToStoreKeyReference(
132
+ storesForCustomer = await this.storeReferenceToStoreKeyReference(
116
133
  draft.stores,
117
134
  context.projectKey,
118
135
  );
119
136
  }
120
137
 
121
138
  const resource: Customer = {
122
- ...getBaseResourceProperties(),
139
+ ...getBaseResourceProperties(context.clientId),
123
140
  key: draft.key,
124
141
  authenticationMode: draft.authenticationMode || "Password",
125
142
  firstName: draft.firstName,
@@ -139,38 +156,43 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
139
156
  defaultShippingAddressId: defaultShippingAddressId,
140
157
  shippingAddressIds: shippingAddressIds,
141
158
  billingAddressIds: billingAddressIds,
142
- custom: createCustomFields(
159
+ custom: await createCustomFields(
143
160
  draft.custom,
144
161
  context.projectKey,
145
162
  this._storage,
146
163
  ),
147
164
  stores: storesForCustomer,
165
+ customerGroupAssignments: [],
148
166
  } satisfies unknown as Customer;
149
167
 
150
- return this.saveNew(context, resource);
168
+ return await this.saveNew(context, resource);
151
169
  }
152
170
 
153
- saveUpdate(
171
+ async saveUpdate(
154
172
  context: RepositoryContext,
155
173
  version: number,
156
174
  resource: ShallowWritable<ResourceMap["customer"]>,
157
- ): ShallowWritable<ResourceMap["customer"]> {
175
+ ): Promise<ShallowWritable<ResourceMap["customer"]>> {
158
176
  // Also update lowercaseEmail attribute
159
177
  const updatedResource: Customer = {
160
178
  ...resource,
161
179
  lowercaseEmail: resource.email.toLowerCase(),
162
180
  } satisfies unknown as Customer;
163
181
 
164
- return super.saveUpdate(context, version, updatedResource);
182
+ return await super.saveUpdate(context, version, updatedResource);
165
183
  }
166
184
 
167
- passwordResetToken(
185
+ async passwordResetToken(
168
186
  context: RepositoryContext,
169
187
  request: CustomerCreatePasswordResetToken,
170
- ): CustomerToken {
171
- const results = this._storage.query(context.projectKey, this.getTypeId(), {
172
- where: [`email="${request.email.toLocaleLowerCase()}"`],
173
- });
188
+ ): Promise<CustomerToken> {
189
+ const results = await this._storage.query(
190
+ context.projectKey,
191
+ this.getTypeId(),
192
+ {
193
+ where: [`email="${request.email.toLocaleLowerCase()}"`],
194
+ },
195
+ );
174
196
  if (results.count === 0) {
175
197
  throw new CommercetoolsError<ResourceNotFoundError>({
176
198
  code: "ResourceNotFound",
@@ -182,7 +204,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
182
204
 
183
205
  const expiresAt = new Date(Date.now() + ttlMinutes * 60 * 1000);
184
206
  const customer = results.results[0] as Customer;
185
- const rest = getBaseResourceProperties();
207
+ const rest = getBaseResourceProperties(context.clientId);
186
208
 
187
209
  const token = createPasswordResetToken(customer, expiresAt);
188
210
 
@@ -197,7 +219,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
197
219
  };
198
220
  }
199
221
 
200
- passwordReset(
222
+ async passwordReset(
201
223
  context: RepositoryContext,
202
224
  resetPassword: CustomerResetPassword | MyCustomerResetPassword,
203
225
  ) {
@@ -211,11 +233,11 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
211
233
  });
212
234
  }
213
235
 
214
- const customer = this._storage.get(
236
+ const customer = (await this._storage.get(
215
237
  context.projectKey,
216
238
  "customer",
217
239
  customerId,
218
- ) as Writable<Customer> | undefined;
240
+ )) as Writable<Customer> | undefined;
219
241
 
220
242
  if (!customer) {
221
243
  throw new CommercetoolsError<ResourceNotFoundError>({
@@ -228,14 +250,21 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
228
250
  customer.version += 1;
229
251
 
230
252
  // Update storage
231
- this._storage.add(context.projectKey, "customer", customer);
253
+ await this._storage.add(context.projectKey, "customer", customer);
232
254
  return customer;
233
255
  }
234
256
 
235
- emailToken(context: RepositoryContext, id: string): CustomerToken {
236
- const results = this._storage.query(context.projectKey, this.getTypeId(), {
237
- where: [`id="${id.toLocaleLowerCase()}"`],
238
- });
257
+ async emailToken(
258
+ context: RepositoryContext,
259
+ id: string,
260
+ ): Promise<CustomerToken> {
261
+ const results = await this._storage.query(
262
+ context.projectKey,
263
+ this.getTypeId(),
264
+ {
265
+ where: [`id="${id.toLocaleLowerCase()}"`],
266
+ },
267
+ );
239
268
  if (results.count === 0) {
240
269
  throw new CommercetoolsError<ResourceNotFoundError>({
241
270
  code: "ResourceNotFound",
@@ -244,7 +273,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
244
273
  }
245
274
  const expiresAt = new Date(Date.now() + 30 * 60);
246
275
  const customer = results.results[0] as Customer;
247
- const rest = getBaseResourceProperties();
276
+ const rest = getBaseResourceProperties(context.clientId);
248
277
 
249
278
  const token = createEmailVerifyToken(customer);
250
279
  return {
@@ -258,7 +287,7 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
258
287
  };
259
288
  }
260
289
 
261
- emailTokenConfirm(
290
+ async emailTokenConfirm(
262
291
  context: RepositoryContext,
263
292
  request: { tokenValue: string },
264
293
  ) {
@@ -270,11 +299,11 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
270
299
  });
271
300
  }
272
301
 
273
- const customer = this._storage.get(
302
+ const customer = (await this._storage.get(
274
303
  context.projectKey,
275
304
  "customer",
276
305
  customerId,
277
- ) as Writable<Customer> | undefined;
306
+ )) as Writable<Customer> | undefined;
278
307
 
279
308
  if (!customer) {
280
309
  throw new CommercetoolsError<ResourceNotFoundError>({
@@ -287,14 +316,14 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
287
316
  customer.version += 1;
288
317
 
289
318
  // Update storage
290
- this._storage.add(context.projectKey, "customer", customer);
319
+ await this._storage.add(context.projectKey, "customer", customer);
291
320
  return customer;
292
321
  }
293
322
 
294
- private storeReferenceToStoreKeyReference(
323
+ private async storeReferenceToStoreKeyReference(
295
324
  draftStores: StoreResourceIdentifier[],
296
325
  projectKey: string,
297
- ): StoreKeyReference[] {
326
+ ): Promise<StoreKeyReference[]> {
298
327
  const storeIds = draftStores
299
328
  .map((storeReference) => storeReference.id)
300
329
  .filter(Boolean);
@@ -302,9 +331,10 @@ export class CustomerRepository extends AbstractResourceRepository<"customer"> {
302
331
  let stores: Store[] = [];
303
332
 
304
333
  if (storeIds.length > 0) {
305
- stores = this._storage.query(projectKey, "store", {
334
+ const storeResult = await this._storage.query(projectKey, "store", {
306
335
  where: storeIds.map((id) => `id="${id}"`),
307
- }).results;
336
+ });
337
+ stores = storeResult.results;
308
338
 
309
339
  if (storeIds.length !== stores.length) {
310
340
  throw new CommercetoolsError<ResourceNotFoundError>({
@@ -5,7 +5,7 @@ import type {
5
5
  CustomerGroupSetCustomTypeAction,
6
6
  CustomerGroupSetKeyAction,
7
7
  } from "@commercetools/platform-sdk";
8
- import { describe, expect, test } from "vitest";
8
+ import { beforeAll, describe, expect, test } from "vitest";
9
9
  import type { Config } from "#src/config.ts";
10
10
  import { getBaseResourceProperties } from "#src/helpers.ts";
11
11
  import { InMemoryStorage } from "#src/storage/index.ts";
@@ -16,32 +16,34 @@ describe("CustomerGroup Repository", () => {
16
16
  const config: Config = { storage, strict: false };
17
17
  const repository = new CustomerGroupRepository(config);
18
18
 
19
- // Add a custom type for testing
20
- storage.add("dummy", "type", {
21
- ...getBaseResourceProperties(),
22
- id: "custom-type-id",
23
- key: "custom-type-key",
24
- name: { "en-US": "Custom Type" },
25
- resourceTypeIds: ["customer-group"],
26
- fieldDefinitions: [
27
- {
28
- name: "description",
29
- label: { "en-US": "Description" },
30
- required: false,
31
- type: { name: "String" },
32
- inputHint: "SingleLine",
33
- },
34
- ],
19
+ beforeAll(async () => {
20
+ // Add a custom type for testing
21
+ await storage.add("dummy", "type", {
22
+ ...getBaseResourceProperties(),
23
+ id: "custom-type-id",
24
+ key: "custom-type-key",
25
+ name: { "en-US": "Custom Type" },
26
+ resourceTypeIds: ["customer-group"],
27
+ fieldDefinitions: [
28
+ {
29
+ name: "description",
30
+ label: { "en-US": "Description" },
31
+ required: false,
32
+ type: { name: "String" },
33
+ inputHint: "SingleLine",
34
+ },
35
+ ],
36
+ });
35
37
  });
36
38
 
37
- test("create customer group", () => {
39
+ test("create customer group", async () => {
38
40
  const draft: CustomerGroupDraft = {
39
41
  key: "premium-customers",
40
42
  groupName: "Premium Customers",
41
43
  };
42
44
 
43
45
  const ctx = { projectKey: "dummy" };
44
- const result = repository.create(ctx, draft);
46
+ const result = await repository.create(ctx, draft);
45
47
 
46
48
  expect(result.id).toBeDefined();
47
49
  expect(result.version).toBe(1);
@@ -50,12 +52,12 @@ describe("CustomerGroup Repository", () => {
50
52
  expect(result.custom).toBeUndefined();
51
53
 
52
54
  // Test that the customer group is stored
53
- const items = repository.query(ctx);
55
+ const items = await repository.query(ctx);
54
56
  expect(items.count).toBe(1);
55
57
  expect(items.results[0].id).toBe(result.id);
56
58
  });
57
59
 
58
- test("create customer group with custom fields", () => {
60
+ test("create customer group with custom fields", async () => {
59
61
  const draft: CustomerGroupDraft = {
60
62
  key: "vip-customers",
61
63
  groupName: "VIP Customers",
@@ -71,7 +73,7 @@ describe("CustomerGroup Repository", () => {
71
73
  };
72
74
 
73
75
  const ctx = { projectKey: "dummy" };
74
- const result = repository.create(ctx, draft);
76
+ const result = await repository.create(ctx, draft);
75
77
 
76
78
  expect(result.id).toBeDefined();
77
79
  expect(result.key).toBe(draft.key);
@@ -80,16 +82,16 @@ describe("CustomerGroup Repository", () => {
80
82
  expect(result.custom?.fields.description).toBe("Very important customers");
81
83
  });
82
84
 
83
- test("update customer group - changeName", () => {
85
+ test("update customer group - changeName", async () => {
84
86
  const draft: CustomerGroupDraft = {
85
87
  key: "test-customers",
86
88
  groupName: "Test Customers",
87
89
  };
88
90
 
89
91
  const ctx = { projectKey: "dummy" };
90
- const customerGroup = repository.create(ctx, draft);
92
+ const customerGroup = await repository.create(ctx, draft);
91
93
 
92
- const result = repository.processUpdateActions(
94
+ const result = await repository.processUpdateActions(
93
95
  ctx,
94
96
  customerGroup,
95
97
  customerGroup.version,
@@ -105,16 +107,16 @@ describe("CustomerGroup Repository", () => {
105
107
  expect(result.version).toBe(customerGroup.version + 1);
106
108
  });
107
109
 
108
- test("update customer group - setKey", () => {
110
+ test("update customer group - setKey", async () => {
109
111
  const draft: CustomerGroupDraft = {
110
112
  key: "test-customers-2",
111
113
  groupName: "Test Customers 2",
112
114
  };
113
115
 
114
116
  const ctx = { projectKey: "dummy" };
115
- const customerGroup = repository.create(ctx, draft);
117
+ const customerGroup = await repository.create(ctx, draft);
116
118
 
117
- const result = repository.processUpdateActions(
119
+ const result = await repository.processUpdateActions(
118
120
  ctx,
119
121
  customerGroup,
120
122
  customerGroup.version,
@@ -130,17 +132,17 @@ describe("CustomerGroup Repository", () => {
130
132
  expect(result.version).toBe(customerGroup.version + 1);
131
133
  });
132
134
 
133
- test("update customer group - setCustomType", () => {
135
+ test("update customer group - setCustomType", async () => {
134
136
  const draft: CustomerGroupDraft = {
135
137
  key: "test-customers-3",
136
138
  groupName: "Test Customers 3",
137
139
  };
138
140
 
139
141
  const ctx = { projectKey: "dummy" };
140
- const customerGroup = repository.create(ctx, draft);
142
+ const customerGroup = await repository.create(ctx, draft);
141
143
 
142
144
  // Set custom type
143
- const result = repository.processUpdateActions(
145
+ const result = await repository.processUpdateActions(
144
146
  ctx,
145
147
  customerGroup,
146
148
  customerGroup.version,
@@ -163,7 +165,7 @@ describe("CustomerGroup Repository", () => {
163
165
  expect(result.version).toBe(customerGroup.version + 1);
164
166
 
165
167
  // Remove custom type
166
- const result2 = repository.processUpdateActions(
168
+ const result2 = await repository.processUpdateActions(
167
169
  ctx,
168
170
  result,
169
171
  result.version,
@@ -178,7 +180,7 @@ describe("CustomerGroup Repository", () => {
178
180
  expect(result2.version).toBe(result.version + 1);
179
181
  });
180
182
 
181
- test("update customer group - setCustomField", () => {
183
+ test("update customer group - setCustomField", async () => {
182
184
  const draft: CustomerGroupDraft = {
183
185
  key: "test-customers-4",
184
186
  groupName: "Test Customers 4",
@@ -194,10 +196,10 @@ describe("CustomerGroup Repository", () => {
194
196
  };
195
197
 
196
198
  const ctx = { projectKey: "dummy" };
197
- const customerGroup = repository.create(ctx, draft);
199
+ const customerGroup = await repository.create(ctx, draft);
198
200
 
199
201
  // Update custom field
200
- const result = repository.processUpdateActions(
202
+ const result = await repository.processUpdateActions(
201
203
  ctx,
202
204
  customerGroup,
203
205
  customerGroup.version,
@@ -214,7 +216,7 @@ describe("CustomerGroup Repository", () => {
214
216
  expect(result.version).toBe(customerGroup.version + 1);
215
217
 
216
218
  // Remove custom field
217
- const result2 = repository.processUpdateActions(
219
+ const result2 = await repository.processUpdateActions(
218
220
  ctx,
219
221
  result,
220
222
  result.version,
@@ -231,32 +233,32 @@ describe("CustomerGroup Repository", () => {
231
233
  expect(result2.version).toBe(result.version + 1);
232
234
  });
233
235
 
234
- test("get and delete customer group", () => {
236
+ test("get and delete customer group", async () => {
235
237
  const draft: CustomerGroupDraft = {
236
238
  key: "delete-test",
237
239
  groupName: "Delete Test",
238
240
  };
239
241
 
240
242
  const ctx = { projectKey: "dummy" };
241
- const customerGroup = repository.create(ctx, draft);
243
+ const customerGroup = await repository.create(ctx, draft);
242
244
 
243
245
  // Test get
244
- const retrieved = repository.get(ctx, customerGroup.id);
246
+ const retrieved = await repository.get(ctx, customerGroup.id);
245
247
  expect(retrieved).toBeDefined();
246
248
  expect(retrieved?.id).toBe(customerGroup.id);
247
249
 
248
250
  // Test getByKey
249
- const retrievedByKey = repository.getByKey(ctx, customerGroup.key!);
251
+ const retrievedByKey = await repository.getByKey(ctx, customerGroup.key!);
250
252
  expect(retrievedByKey).toBeDefined();
251
253
  expect(retrievedByKey?.key).toBe(customerGroup.key);
252
254
 
253
255
  // Test delete
254
- const deleted = repository.delete(ctx, customerGroup.id);
256
+ const deleted = await repository.delete(ctx, customerGroup.id);
255
257
  expect(deleted).toBeDefined();
256
258
  expect(deleted?.id).toBe(customerGroup.id);
257
259
 
258
260
  // Verify it's deleted
259
- const notFound = repository.get(ctx, customerGroup.id);
261
+ const notFound = await repository.get(ctx, customerGroup.id);
260
262
  expect(notFound).toBeNull();
261
263
  });
262
264
  });
@@ -8,6 +8,7 @@ import type {
8
8
  CustomerGroupUpdateAction,
9
9
  } from "@commercetools/platform-sdk";
10
10
  import type { Config } from "#src/config.ts";
11
+ import { CustomerGroupDraftSchema } from "#src/schemas/generated/customer-group.ts";
11
12
  import { getBaseResourceProperties } from "../helpers.ts";
12
13
  import type { Writable } from "../types.ts";
13
14
  import type { UpdateHandlerInterface } from "./abstract.ts";
@@ -22,20 +23,24 @@ export class CustomerGroupRepository extends AbstractResourceRepository<"custome
22
23
  constructor(config: Config) {
23
24
  super("customer-group", config);
24
25
  this.actions = new CustomerGroupUpdateHandler(config.storage);
26
+ this.draftSchema = CustomerGroupDraftSchema;
25
27
  }
26
28
 
27
- create(context: RepositoryContext, draft: CustomerGroupDraft): CustomerGroup {
29
+ async create(
30
+ context: RepositoryContext,
31
+ draft: CustomerGroupDraft,
32
+ ): Promise<CustomerGroup> {
28
33
  const resource: CustomerGroup = {
29
- ...getBaseResourceProperties(),
34
+ ...getBaseResourceProperties(context.clientId),
30
35
  key: draft.key,
31
36
  name: draft.groupName,
32
- custom: createCustomFields(
37
+ custom: await createCustomFields(
33
38
  draft.custom,
34
39
  context.projectKey,
35
40
  this._storage,
36
41
  ),
37
42
  };
38
- return this.saveNew(context, resource);
43
+ return await this.saveNew(context, resource);
39
44
  }
40
45
  }
41
46
 
@@ -56,30 +61,15 @@ class CustomerGroupUpdateHandler
56
61
  resource: Writable<CustomerGroup>,
57
62
  { name, value }: CustomerGroupSetCustomFieldAction,
58
63
  ) {
59
- if (!resource.custom) {
60
- return;
61
- }
62
- if (value === null) {
63
- delete resource.custom.fields[name];
64
- } else {
65
- resource.custom.fields[name] = value;
66
- }
64
+ this._setCustomFieldValues(resource, { name, value });
67
65
  }
68
66
 
69
- setCustomType(
67
+ async setCustomType(
70
68
  context: RepositoryContext,
71
69
  resource: Writable<CustomerGroup>,
72
70
  { type, fields }: CustomerGroupSetCustomTypeAction,
73
71
  ) {
74
- if (type) {
75
- resource.custom = createCustomFields(
76
- { type, fields },
77
- context.projectKey,
78
- this._storage,
79
- );
80
- } else {
81
- resource.custom = undefined;
82
- }
72
+ await this._setCustomType(context, resource, { type, fields });
83
73
  }
84
74
 
85
75
  setKey(
@@ -18,7 +18,6 @@ import type {
18
18
  import type { Writable } from "#src/types.ts";
19
19
  import type { UpdateHandlerInterface } from "../abstract.ts";
20
20
  import { AbstractUpdateHandler, type RepositoryContext } from "../abstract.ts";
21
- import { createCustomFields } from "../helpers.ts";
22
21
 
23
22
  export class DiscountCodeUpdateHandler
24
23
  extends AbstractUpdateHandler
@@ -59,30 +58,15 @@ export class DiscountCodeUpdateHandler
59
58
  resource: Writable<DiscountCode>,
60
59
  { name, value }: DiscountCodeSetCustomFieldAction,
61
60
  ) {
62
- if (!resource.custom) {
63
- return;
64
- }
65
- if (value === null) {
66
- delete resource.custom.fields[name];
67
- } else {
68
- resource.custom.fields[name] = value;
69
- }
61
+ this._setCustomFieldValues(resource, { name, value });
70
62
  }
71
63
 
72
- setCustomType(
64
+ async setCustomType(
73
65
  context: RepositoryContext,
74
66
  resource: Writable<DiscountCode>,
75
67
  { type, fields }: DiscountCodeSetCustomTypeAction,
76
68
  ) {
77
- if (type) {
78
- resource.custom = createCustomFields(
79
- { type, fields },
80
- context.projectKey,
81
- this._storage,
82
- );
83
- } else {
84
- resource.custom = undefined;
85
- }
69
+ await this._setCustomType(context, resource, { type, fields });
86
70
  }
87
71
 
88
72
  setDescription(