@labdigital/commercetools-mock 2.65.1 → 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 +3771 -2654
  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 +89 -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
@@ -5,6 +5,7 @@ import type {
5
5
  } from "@commercetools/platform-sdk";
6
6
  import type { Config } from "#src/config.ts";
7
7
  import { getBaseResourceProperties } from "#src/helpers.ts";
8
+ import { DiscountCodeDraftSchema } from "#src/schemas/generated/discount-code.ts";
8
9
  import {
9
10
  AbstractResourceRepository,
10
11
  type RepositoryContext,
@@ -16,11 +17,15 @@ export class DiscountCodeRepository extends AbstractResourceRepository<"discount
16
17
  constructor(config: Config) {
17
18
  super("discount-code", config);
18
19
  this.actions = new DiscountCodeUpdateHandler(config.storage);
20
+ this.draftSchema = DiscountCodeDraftSchema;
19
21
  }
20
22
 
21
- create(context: RepositoryContext, draft: DiscountCodeDraft): DiscountCode {
23
+ async create(
24
+ context: RepositoryContext,
25
+ draft: DiscountCodeDraft,
26
+ ): Promise<DiscountCode> {
22
27
  const resource: DiscountCode = {
23
- ...getBaseResourceProperties(),
28
+ ...getBaseResourceProperties(context.clientId),
24
29
  applicationVersion: 1,
25
30
  cartDiscounts: draft.cartDiscounts.map(
26
31
  (obj): CartDiscountReference => ({
@@ -39,12 +44,12 @@ export class DiscountCodeRepository extends AbstractResourceRepository<"discount
39
44
  validUntil: draft.validUntil,
40
45
  maxApplications: draft.maxApplications,
41
46
  maxApplicationsPerCustomer: draft.maxApplicationsPerCustomer,
42
- custom: createCustomFields(
47
+ custom: await createCustomFields(
43
48
  draft.custom,
44
49
  context.projectKey,
45
50
  this._storage,
46
51
  ),
47
52
  };
48
- return this.saveNew(context, resource);
53
+ return await this.saveNew(context, resource);
49
54
  }
50
55
  }
@@ -4,6 +4,7 @@ import type {
4
4
  } from "@commercetools/platform-sdk";
5
5
  import type { Config } from "#src/config.ts";
6
6
  import { getBaseResourceProperties } from "#src/helpers.ts";
7
+ import { DiscountGroupDraftSchema } from "#src/schemas/generated/discount-group.ts";
7
8
  import {
8
9
  AbstractResourceRepository,
9
10
  type RepositoryContext,
@@ -14,17 +15,21 @@ export class DiscountGroupRepository extends AbstractResourceRepository<"discoun
14
15
  constructor(config: Config) {
15
16
  super("discount-group", config);
16
17
  this.actions = new DiscountGroupUpdateHandler(config.storage);
18
+ this.draftSchema = DiscountGroupDraftSchema;
17
19
  }
18
20
 
19
- create(context: RepositoryContext, draft: DiscountGroupDraft): DiscountGroup {
21
+ async create(
22
+ context: RepositoryContext,
23
+ draft: DiscountGroupDraft,
24
+ ): Promise<DiscountGroup> {
20
25
  const resource: DiscountGroup = {
21
- ...getBaseResourceProperties(),
26
+ ...getBaseResourceProperties(context.clientId),
22
27
  description: draft.description,
23
28
  name: draft.name,
24
29
  key: draft.key,
25
30
  sortOrder: draft.sortOrder,
26
31
  isActive: true,
27
32
  };
28
- return this.saveNew(context, resource);
33
+ return await this.saveNew(context, resource);
29
34
  }
30
35
  }
@@ -16,7 +16,7 @@ describe("Extension Repository", () => {
16
16
  const config: Config = { storage, strict: false };
17
17
  const repository = new ExtensionRepository(config);
18
18
 
19
- test("create extension with HTTP destination", () => {
19
+ test("create extension with HTTP destination", async () => {
20
20
  const draft: ExtensionDraft = {
21
21
  key: "test-extension",
22
22
  timeoutInMs: 2000,
@@ -37,7 +37,7 @@ describe("Extension Repository", () => {
37
37
  };
38
38
 
39
39
  const ctx = { projectKey: "dummy" };
40
- const result = repository.create(ctx, draft);
40
+ const result = await repository.create(ctx, draft);
41
41
 
42
42
  expect(result.id).toBeDefined();
43
43
  expect(result.key).toBe(draft.key);
@@ -46,11 +46,11 @@ describe("Extension Repository", () => {
46
46
  expect(result.triggers).toEqual(draft.triggers);
47
47
 
48
48
  // Test that the extension is stored
49
- const items = repository.query(ctx);
49
+ const items = await repository.query(ctx);
50
50
  expect(items.count).toBe(1);
51
51
  });
52
52
 
53
- test("create extension with AWSLambda destination", () => {
53
+ test("create extension with AWSLambda destination", async () => {
54
54
  const draft: ExtensionDraft = {
55
55
  key: "aws-extension",
56
56
  destination: {
@@ -68,7 +68,7 @@ describe("Extension Repository", () => {
68
68
  };
69
69
 
70
70
  const ctx = { projectKey: "dummy" };
71
- const result = repository.create(ctx, draft);
71
+ const result = await repository.create(ctx, draft);
72
72
 
73
73
  expect(result.id).toBeDefined();
74
74
  expect(result.key).toBe(draft.key);
@@ -76,7 +76,7 @@ describe("Extension Repository", () => {
76
76
  expect(result.triggers).toEqual(draft.triggers);
77
77
  });
78
78
 
79
- test("postProcessResource masks HTTP authentication header", () => {
79
+ test("postProcessResource masks HTTP authentication header", async () => {
80
80
  const extension: Extension = {
81
81
  id: "test-id",
82
82
  version: 1,
@@ -95,7 +95,7 @@ describe("Extension Repository", () => {
95
95
  };
96
96
 
97
97
  const ctx = { projectKey: "dummy" };
98
- const result = repository.postProcessResource(ctx, extension);
98
+ const result = await repository.postProcessResource(ctx, extension);
99
99
 
100
100
  expect(result.destination.type).toBe("HTTP");
101
101
  if (
@@ -106,7 +106,7 @@ describe("Extension Repository", () => {
106
106
  }
107
107
  });
108
108
 
109
- test("postProcessResource masks AWSLambda access secret", () => {
109
+ test("postProcessResource masks AWSLambda access secret", async () => {
110
110
  const extension: Extension = {
111
111
  id: "test-id",
112
112
  version: 1,
@@ -123,7 +123,7 @@ describe("Extension Repository", () => {
123
123
  };
124
124
 
125
125
  const ctx = { projectKey: "dummy" };
126
- const result = repository.postProcessResource(ctx, extension);
126
+ const result = await repository.postProcessResource(ctx, extension);
127
127
 
128
128
  expect(result.destination.type).toBe("AWSLambda");
129
129
  if (result.destination.type === "AWSLambda") {
@@ -131,7 +131,7 @@ describe("Extension Repository", () => {
131
131
  }
132
132
  });
133
133
 
134
- test("update extension - changeDestination", () => {
134
+ test("update extension - changeDestination", async () => {
135
135
  const draft: ExtensionDraft = {
136
136
  key: "test-extension",
137
137
  destination: {
@@ -147,14 +147,14 @@ describe("Extension Repository", () => {
147
147
  };
148
148
 
149
149
  const ctx = { projectKey: "dummy" };
150
- const extension = repository.create(ctx, draft);
150
+ const extension = await repository.create(ctx, draft);
151
151
 
152
152
  const newDestination = {
153
153
  type: "HTTP" as const,
154
154
  url: "https://new-example.com/webhook",
155
155
  };
156
156
 
157
- const result = repository.processUpdateActions(
157
+ const result = await repository.processUpdateActions(
158
158
  ctx,
159
159
  extension,
160
160
  extension.version,
@@ -172,7 +172,7 @@ describe("Extension Repository", () => {
172
172
  expect(result.version).toBe(extension.version + 1);
173
173
  });
174
174
 
175
- test("update extension - changeTriggers", () => {
175
+ test("update extension - changeTriggers", async () => {
176
176
  const draft: ExtensionDraft = {
177
177
  key: "test-extension",
178
178
  destination: {
@@ -188,7 +188,7 @@ describe("Extension Repository", () => {
188
188
  };
189
189
 
190
190
  const ctx = { projectKey: "dummy" };
191
- const extension = repository.create(ctx, draft);
191
+ const extension = await repository.create(ctx, draft);
192
192
 
193
193
  const newTriggers = [
194
194
  {
@@ -197,7 +197,7 @@ describe("Extension Repository", () => {
197
197
  },
198
198
  ];
199
199
 
200
- const result = repository.processUpdateActions(
200
+ const result = await repository.processUpdateActions(
201
201
  ctx,
202
202
  extension,
203
203
  extension.version,
@@ -213,7 +213,7 @@ describe("Extension Repository", () => {
213
213
  expect(result.version).toBe(extension.version + 1);
214
214
  });
215
215
 
216
- test("update extension - setKey", () => {
216
+ test("update extension - setKey", async () => {
217
217
  const draft: ExtensionDraft = {
218
218
  key: "test-extension",
219
219
  destination: {
@@ -224,9 +224,9 @@ describe("Extension Repository", () => {
224
224
  };
225
225
 
226
226
  const ctx = { projectKey: "dummy" };
227
- const extension = repository.create(ctx, draft);
227
+ const extension = await repository.create(ctx, draft);
228
228
 
229
- const result = repository.processUpdateActions(
229
+ const result = await repository.processUpdateActions(
230
230
  ctx,
231
231
  extension,
232
232
  extension.version,
@@ -242,7 +242,7 @@ describe("Extension Repository", () => {
242
242
  expect(result.version).toBe(extension.version + 1);
243
243
  });
244
244
 
245
- test("update extension - setTimeoutInMs", () => {
245
+ test("update extension - setTimeoutInMs", async () => {
246
246
  const draft: ExtensionDraft = {
247
247
  key: "test-extension",
248
248
  destination: {
@@ -253,9 +253,9 @@ describe("Extension Repository", () => {
253
253
  };
254
254
 
255
255
  const ctx = { projectKey: "dummy" };
256
- const extension = repository.create(ctx, draft);
256
+ const extension = await repository.create(ctx, draft);
257
257
 
258
- const result = repository.processUpdateActions(
258
+ const result = await repository.processUpdateActions(
259
259
  ctx,
260
260
  extension,
261
261
  extension.version,
@@ -271,7 +271,7 @@ describe("Extension Repository", () => {
271
271
  expect(result.version).toBe(extension.version + 1);
272
272
  });
273
273
 
274
- test("get and delete extension", () => {
274
+ test("get and delete extension", async () => {
275
275
  const draft: ExtensionDraft = {
276
276
  key: "test-extension",
277
277
  destination: {
@@ -282,25 +282,25 @@ describe("Extension Repository", () => {
282
282
  };
283
283
 
284
284
  const ctx = { projectKey: "dummy" };
285
- const extension = repository.create(ctx, draft);
285
+ const extension = await repository.create(ctx, draft);
286
286
 
287
287
  // Test get
288
- const retrieved = repository.get(ctx, extension.id);
288
+ const retrieved = await repository.get(ctx, extension.id);
289
289
  expect(retrieved).toBeDefined();
290
290
  expect(retrieved?.id).toBe(extension.id);
291
291
 
292
292
  // Test getByKey
293
- const retrievedByKey = repository.getByKey(ctx, extension.key!);
293
+ const retrievedByKey = await repository.getByKey(ctx, extension.key!);
294
294
  expect(retrievedByKey).toBeDefined();
295
295
  expect(retrievedByKey?.key).toBe(extension.key);
296
296
 
297
297
  // Test delete
298
- const deleted = repository.delete(ctx, extension.id);
298
+ const deleted = await repository.delete(ctx, extension.id);
299
299
  expect(deleted).toBeDefined();
300
300
  expect(deleted?.id).toBe(extension.id);
301
301
 
302
302
  // Verify it's deleted
303
- const notFound = repository.get(ctx, extension.id);
303
+ const notFound = await repository.get(ctx, extension.id);
304
304
  expect(notFound).toBeNull();
305
305
  });
306
306
  });
@@ -8,6 +8,7 @@ import type {
8
8
  ExtensionUpdateAction,
9
9
  } from "@commercetools/platform-sdk";
10
10
  import type { Config } from "#src/config.ts";
11
+ import { ExtensionDraftSchema } from "#src/schemas/generated/extension.ts";
11
12
  import { getBaseResourceProperties } from "../helpers.ts";
12
13
  import { maskSecretValue } from "../lib/masking.ts";
13
14
  import type { Writable } from "../types.ts";
@@ -22,23 +23,27 @@ export class ExtensionRepository extends AbstractResourceRepository<"extension">
22
23
  constructor(config: Config) {
23
24
  super("extension", config);
24
25
  this.actions = new ExtensionUpdateHandler(config.storage);
26
+ this.draftSchema = ExtensionDraftSchema;
25
27
  }
26
28
 
27
- create(context: RepositoryContext, draft: ExtensionDraft): Extension {
29
+ async create(
30
+ context: RepositoryContext,
31
+ draft: ExtensionDraft,
32
+ ): Promise<Extension> {
28
33
  const resource: Extension = {
29
- ...getBaseResourceProperties(),
34
+ ...getBaseResourceProperties(context.clientId),
30
35
  key: draft.key,
31
36
  timeoutInMs: draft.timeoutInMs,
32
37
  destination: draft.destination,
33
38
  triggers: draft.triggers,
34
39
  };
35
- return this.saveNew(context, resource);
40
+ return await this.saveNew(context, resource);
36
41
  }
37
42
 
38
- postProcessResource(
43
+ async postProcessResource(
39
44
  context: RepositoryContext,
40
45
  resource: Extension,
41
- ): Extension {
46
+ ): Promise<Extension> {
42
47
  if (resource) {
43
48
  const extension = resource as Extension;
44
49
  if (
@@ -16,6 +16,7 @@ import type {
16
16
  CustomFieldsDraft,
17
17
  HighPrecisionMoney,
18
18
  HighPrecisionMoneyDraft,
19
+ InvalidInputError,
19
20
  InvalidJsonInputError,
20
21
  Price,
21
22
  PriceDraft,
@@ -31,7 +32,7 @@ import type {
31
32
  TypedMoney,
32
33
  } from "@commercetools/platform-sdk";
33
34
  import { Decimal } from "decimal.js/decimal";
34
- import type { Request } from "express";
35
+ import type { FastifyRequest } from "fastify";
35
36
  import { v4 as uuidv4 } from "uuid";
36
37
  import { CommercetoolsError } from "#src/exceptions.ts";
37
38
  import type { AbstractStorage } from "../storage/index.ts";
@@ -45,7 +46,14 @@ export const createAddress = (
45
46
  if (!base) return undefined;
46
47
 
47
48
  if (!base?.country) {
48
- throw new Error("Country is required");
49
+ throw new CommercetoolsError<InvalidJsonInputError>(
50
+ {
51
+ code: "InvalidJsonInput",
52
+ message: "Country is required",
53
+ detailedErrorMessage: "Country is required",
54
+ },
55
+ 400,
56
+ );
49
57
  }
50
58
 
51
59
  // Generate a random 8-character alphanumeric string
@@ -58,22 +66,27 @@ export const createAddress = (
58
66
  };
59
67
  };
60
68
 
61
- export const createCustomFields = (
69
+ export const createCustomFields = async (
62
70
  draft: CustomFieldsDraft | undefined,
63
71
  projectKey: string,
64
72
  storage: AbstractStorage,
65
- ): CustomFields | undefined => {
73
+ ): Promise<CustomFields | undefined> => {
66
74
  if (!draft) return undefined;
67
75
  if (!draft.type) return undefined;
68
76
  if (!draft.type.typeId) return undefined;
69
- const typeResource = storage.getByResourceIdentifier(
77
+ const typeResource = (await storage.getByResourceIdentifier(
70
78
  projectKey,
71
79
  draft.type,
72
- ) as Type;
80
+ )) as Type;
73
81
 
74
82
  if (!typeResource) {
75
- throw new Error(
76
- `No type '${draft.type.typeId}' with id=${draft.type.id} or key=${draft.type.key}`,
83
+ throw new CommercetoolsError<ReferencedResourceNotFoundError>(
84
+ {
85
+ code: "ReferencedResourceNotFound",
86
+ typeId: draft.type.typeId,
87
+ message: `No type '${draft.type.typeId}' with id=${draft.type.id} or key=${draft.type.key}`,
88
+ },
89
+ 400,
77
90
  );
78
91
  }
79
92
 
@@ -106,7 +119,13 @@ export const roundDecimal = (decimal: Decimal, roundingMode: RoundingMode) => {
106
119
  case "HalfDown":
107
120
  return decimal.toDecimalPlaces(0, Decimal.ROUND_HALF_DOWN);
108
121
  default:
109
- throw new Error(`Unknown rounding mode: ${roundingMode}`);
122
+ throw new CommercetoolsError<InvalidInputError>(
123
+ {
124
+ code: "InvalidInput",
125
+ message: `Unknown rounding mode: ${roundingMode}`,
126
+ },
127
+ 400,
128
+ );
110
129
  }
111
130
  };
112
131
 
@@ -190,11 +209,25 @@ export const createHighPrecisionMoney = (
190
209
  value: HighPrecisionMoney | HighPrecisionMoneyDraft,
191
210
  ): HighPrecisionMoney => {
192
211
  if (value.preciseAmount === undefined) {
193
- throw new Error("HighPrecisionMoney requires preciseAmount");
212
+ throw new CommercetoolsError<InvalidJsonInputError>(
213
+ {
214
+ code: "InvalidJsonInput",
215
+ message: "HighPrecisionMoney requires preciseAmount",
216
+ detailedErrorMessage: "HighPrecisionMoney requires preciseAmount",
217
+ },
218
+ 400,
219
+ );
194
220
  }
195
221
 
196
222
  if (value.fractionDigits === undefined) {
197
- throw new Error("HighPrecisionMoney requires fractionDigits");
223
+ throw new CommercetoolsError<InvalidJsonInputError>(
224
+ {
225
+ code: "InvalidJsonInput",
226
+ message: "HighPrecisionMoney requires fractionDigits",
227
+ detailedErrorMessage: "HighPrecisionMoney requires fractionDigits",
228
+ },
229
+ 400,
230
+ );
198
231
  }
199
232
 
200
233
  const centAmount =
@@ -252,15 +285,22 @@ export const calculateMoneyTotalCentAmount = (
252
285
  );
253
286
  };
254
287
 
255
- export const resolveStoreReference = (
288
+ export const resolveStoreReference = async (
256
289
  ref: StoreResourceIdentifier | undefined,
257
290
  projectKey: string,
258
291
  storage: AbstractStorage,
259
- ): StoreKeyReference | undefined => {
292
+ ): Promise<StoreKeyReference | undefined> => {
260
293
  if (!ref) return undefined;
261
- const resource = storage.getByResourceIdentifier(projectKey, ref);
294
+ const resource = await storage.getByResourceIdentifier(projectKey, ref);
262
295
  if (!resource) {
263
- throw new Error("No such store");
296
+ throw new CommercetoolsError<ReferencedResourceNotFoundError>(
297
+ {
298
+ code: "ReferencedResourceNotFound",
299
+ typeId: "store",
300
+ message: "The referenced object of type 'store' was not found.",
301
+ },
302
+ 400,
303
+ );
264
304
  }
265
305
 
266
306
  const store = resource as Store;
@@ -270,11 +310,11 @@ export const resolveStoreReference = (
270
310
  };
271
311
  };
272
312
 
273
- export const getReferenceFromResourceIdentifier = <T extends Reference>(
313
+ export const getReferenceFromResourceIdentifier = async <T extends Reference>(
274
314
  resourceIdentifier: ResourceIdentifier,
275
315
  projectKey: string,
276
316
  storage: AbstractStorage,
277
- ): T => {
317
+ ): Promise<T> => {
278
318
  if (!resourceIdentifier.id && !resourceIdentifier.key) {
279
319
  throw new CommercetoolsError<InvalidJsonInputError>(
280
320
  {
@@ -286,7 +326,7 @@ export const getReferenceFromResourceIdentifier = <T extends Reference>(
286
326
  );
287
327
  }
288
328
 
289
- const resource = storage.getByResourceIdentifier(
329
+ const resource = await storage.getByResourceIdentifier(
290
330
  projectKey,
291
331
  resourceIdentifier,
292
332
  );
@@ -311,25 +351,32 @@ export const getReferenceFromResourceIdentifier = <T extends Reference>(
311
351
  } as unknown as T;
312
352
  };
313
353
 
314
- export const getStoreKeyReference = (
354
+ export const getStoreKeyReference = async (
315
355
  id: StoreResourceIdentifier,
316
356
  projectKey: string,
317
357
  storage: AbstractStorage,
318
- ): StoreKeyReference => {
358
+ ): Promise<StoreKeyReference> => {
319
359
  if (id.key) {
320
360
  return {
321
361
  typeId: "store",
322
362
  key: id.key,
323
363
  };
324
364
  }
325
- const value = getReferenceFromResourceIdentifier<StoreReference>(
365
+ const value = await getReferenceFromResourceIdentifier<StoreReference>(
326
366
  id,
327
367
  projectKey,
328
368
  storage,
329
369
  );
330
370
 
331
371
  if (!value.obj?.key) {
332
- throw new Error("No store found for reference");
372
+ throw new CommercetoolsError<ReferencedResourceNotFoundError>(
373
+ {
374
+ code: "ReferencedResourceNotFound",
375
+ typeId: "store",
376
+ message: "The referenced object of type 'store' was not found.",
377
+ },
378
+ 400,
379
+ );
333
380
  }
334
381
  return {
335
382
  typeId: "store",
@@ -337,31 +384,38 @@ export const getStoreKeyReference = (
337
384
  };
338
385
  };
339
386
 
340
- export const getRepositoryContext = (request: Request): RepositoryContext => ({
387
+ export const getRepositoryContext = (
388
+ request: FastifyRequest<{ Params: Record<string, string> }>,
389
+ ): RepositoryContext => ({
341
390
  projectKey: request.params.projectKey,
342
391
  storeKey: request.params.storeKey,
392
+ clientId: request.credentials?.clientId,
343
393
  });
344
394
 
345
- export const createAssociate = (
395
+ export const createAssociate = async (
346
396
  a: AssociateDraft,
347
397
  projectKey: string,
348
398
  storage: AbstractStorage,
349
- ): Associate | undefined => {
399
+ ): Promise<Associate | undefined> => {
350
400
  if (!a) return undefined;
351
401
 
352
402
  if (!a.associateRoleAssignments) {
353
- throw new Error("AssociateRoleAssignments is required");
403
+ throw new CommercetoolsError<InvalidJsonInputError>(
404
+ {
405
+ code: "InvalidJsonInput",
406
+ message: "AssociateRoleAssignments is required",
407
+ detailedErrorMessage: "AssociateRoleAssignments is required",
408
+ },
409
+ 400,
410
+ );
354
411
  }
355
412
 
356
- return {
357
- customer: getReferenceFromResourceIdentifier(
358
- a.customer,
359
- projectKey,
360
- storage,
361
- ),
362
- associateRoleAssignments: a.associateRoleAssignments?.map(
363
- (a: AssociateRoleAssignmentDraft): AssociateRoleAssignment => ({
364
- associateRole: getAssociateRoleKeyReference(
413
+ const associateRoleAssignments = await Promise.all(
414
+ a.associateRoleAssignments.map(
415
+ async (
416
+ a: AssociateRoleAssignmentDraft,
417
+ ): Promise<AssociateRoleAssignment> => ({
418
+ associateRole: await getAssociateRoleKeyReference(
365
419
  a.associateRole,
366
420
  projectKey,
367
421
  storage,
@@ -369,14 +423,23 @@ export const createAssociate = (
369
423
  inheritance: a.inheritance as string,
370
424
  }),
371
425
  ),
426
+ );
427
+
428
+ return {
429
+ customer: await getReferenceFromResourceIdentifier(
430
+ a.customer,
431
+ projectKey,
432
+ storage,
433
+ ),
434
+ associateRoleAssignments,
372
435
  };
373
436
  };
374
437
 
375
- export const getAssociateRoleKeyReference = (
438
+ export const getAssociateRoleKeyReference = async (
376
439
  id: AssociateRoleResourceIdentifier,
377
440
  projectKey: string,
378
441
  storage: AbstractStorage,
379
- ): AssociateRoleKeyReference => {
442
+ ): Promise<AssociateRoleKeyReference> => {
380
443
  if (id.key) {
381
444
  return {
382
445
  typeId: "associate-role",
@@ -384,14 +447,23 @@ export const getAssociateRoleKeyReference = (
384
447
  };
385
448
  }
386
449
 
387
- const value = getReferenceFromResourceIdentifier<AssociateRoleReference>(
388
- id,
389
- projectKey,
390
- storage,
391
- );
450
+ const value =
451
+ await getReferenceFromResourceIdentifier<AssociateRoleReference>(
452
+ id,
453
+ projectKey,
454
+ storage,
455
+ );
392
456
 
393
457
  if (!value.obj?.key) {
394
- throw new Error("No associate-role found for reference");
458
+ throw new CommercetoolsError<ReferencedResourceNotFoundError>(
459
+ {
460
+ code: "ReferencedResourceNotFound",
461
+ typeId: "associate-role",
462
+ message:
463
+ "The referenced object of type 'associate-role' was not found.",
464
+ },
465
+ 400,
466
+ );
395
467
  }
396
468
 
397
469
  return {
@@ -400,11 +472,11 @@ export const getAssociateRoleKeyReference = (
400
472
  };
401
473
  };
402
474
 
403
- export const getBusinessUnitKeyReference = (
475
+ export const getBusinessUnitKeyReference = async (
404
476
  id: BusinessUnitResourceIdentifier,
405
477
  projectKey: string,
406
478
  storage: AbstractStorage,
407
- ): BusinessUnitKeyReference => {
479
+ ): Promise<BusinessUnitKeyReference> => {
408
480
  if (id.key) {
409
481
  return {
410
482
  typeId: "business-unit",
@@ -412,13 +484,20 @@ export const getBusinessUnitKeyReference = (
412
484
  };
413
485
  }
414
486
 
415
- const resource = storage.getByResourceIdentifier<"business-unit">(
487
+ const resource = await storage.getByResourceIdentifier<"business-unit">(
416
488
  projectKey,
417
489
  id,
418
490
  );
419
491
 
420
492
  if (!resource?.key) {
421
- throw new Error("No business-unit found for reference");
493
+ throw new CommercetoolsError<ReferencedResourceNotFoundError>(
494
+ {
495
+ code: "ReferencedResourceNotFound",
496
+ typeId: "business-unit",
497
+ message: "The referenced object of type 'business-unit' was not found.",
498
+ },
499
+ 400,
500
+ );
422
501
  }
423
502
 
424
503
  return {
@@ -43,36 +43,15 @@ export class InventoryEntryUpdateHandler
43
43
  resource: InventoryEntry,
44
44
  { name, value }: InventoryEntrySetCustomFieldAction,
45
45
  ) {
46
- if (!resource.custom) {
47
- throw new Error("Resource has no custom field");
48
- }
49
- resource.custom.fields[name] = value;
46
+ this._setCustomFieldValues(resource, { name, value });
50
47
  }
51
48
 
52
- setCustomType(
49
+ async setCustomType(
53
50
  context: RepositoryContext,
54
51
  resource: Writable<InventoryEntry>,
55
52
  { type, fields }: InventoryEntrySetCustomTypeAction,
56
53
  ) {
57
- if (!type) {
58
- resource.custom = undefined;
59
- } else {
60
- const resolvedType = this._storage.getByResourceIdentifier(
61
- context.projectKey,
62
- type,
63
- );
64
- if (!resolvedType) {
65
- throw new Error(`Type ${type} not found`);
66
- }
67
-
68
- resource.custom = {
69
- type: {
70
- typeId: "type",
71
- id: resolvedType.id,
72
- },
73
- fields: fields || {},
74
- };
75
- }
54
+ await this._setCustomType(context, resource, { type, fields });
76
55
  }
77
56
 
78
57
  setExpectedDelivery(