@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
@@ -0,0 +1,29 @@
1
+ import type {
2
+ QuoteRequest,
3
+ QuoteRequestDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const quoteRequestDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<QuoteRequestDraft, QuoteRequestDraft, QuoteRequest>(
10
+ ({ onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/quote-requests",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ cart: {
23
+ typeId: "cart" as const,
24
+ id: "placeholder-cart-id",
25
+ },
26
+ cartVersion: 1,
27
+ };
28
+ },
29
+ );
@@ -0,0 +1,33 @@
1
+ import type {
2
+ RecurrencePolicy,
3
+ RecurrencePolicyDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const recurrencePolicyDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<
10
+ RecurrencePolicyDraft,
11
+ RecurrencePolicyDraft,
12
+ RecurrencePolicy
13
+ >(({ sequence, onCreate }) => {
14
+ onCreate(async (draft) => {
15
+ const response = await m.app.inject({
16
+ method: "POST",
17
+ url: "/dummy/recurrence-policies",
18
+ payload: draft,
19
+ });
20
+
21
+ return response.json();
22
+ });
23
+
24
+ return {
25
+ key: `recurrence-policy-${sequence}`,
26
+ name: { en: `Recurrence Policy ${sequence}` },
27
+ schedule: {
28
+ type: "standard",
29
+ value: 1,
30
+ intervalUnit: "Months",
31
+ },
32
+ };
33
+ });
@@ -0,0 +1,32 @@
1
+ import type {
2
+ RecurringOrder,
3
+ RecurringOrderDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const recurringOrderDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<RecurringOrderDraft, RecurringOrderDraft, RecurringOrder>(
10
+ ({ sequence, onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/recurring-orders",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ key: `recurring-order-${sequence}`,
23
+ cart: {
24
+ typeId: "cart" as const,
25
+ id: "placeholder-cart-id",
26
+ },
27
+ cartVersion: 1,
28
+ startsAt: "2025-01-01T10:00:00.000Z",
29
+ expiresAt: "2025-12-31T23:59:59.000Z",
30
+ };
31
+ },
32
+ );
@@ -0,0 +1,24 @@
1
+ import type { Review, ReviewDraft } from "@commercetools/platform-sdk";
2
+ import { Factory } from "fishery";
3
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
4
+
5
+ export const reviewDraftFactory = (m: CommercetoolsMock) =>
6
+ Factory.define<ReviewDraft, ReviewDraft, Review>(({ sequence, onCreate }) => {
7
+ onCreate(async (draft) => {
8
+ const response = await m.app.inject({
9
+ method: "POST",
10
+ url: "/dummy/reviews",
11
+ payload: draft,
12
+ });
13
+
14
+ return response.json();
15
+ });
16
+
17
+ return {
18
+ key: `review-${sequence}`,
19
+ authorName: `Author ${sequence}`,
20
+ title: `Review ${sequence}`,
21
+ text: `Review text ${sequence}`,
22
+ rating: 5,
23
+ };
24
+ });
@@ -0,0 +1,31 @@
1
+ import type {
2
+ ShippingMethod,
3
+ ShippingMethodDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const shippingMethodDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<ShippingMethodDraft, ShippingMethodDraft, ShippingMethod>(
10
+ ({ sequence, onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/shipping-methods",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ name: `Shipping Method ${sequence}`,
23
+ taxCategory: {
24
+ typeId: "tax-category",
25
+ key: `tax-category-${sequence}`,
26
+ },
27
+ isDefault: true,
28
+ zoneRates: [],
29
+ };
30
+ },
31
+ );
@@ -0,0 +1,25 @@
1
+ import type {
2
+ ShoppingList,
3
+ ShoppingListDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const shoppingListDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<ShoppingListDraft, ShoppingListDraft, ShoppingList>(
10
+ ({ sequence, onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/shopping-lists",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ name: { en: `Shopping List ${sequence}` },
23
+ };
24
+ },
25
+ );
@@ -0,0 +1,31 @@
1
+ import type {
2
+ StandalonePrice,
3
+ StandalonePriceDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const standalonePriceDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<StandalonePriceDraft, StandalonePriceDraft, StandalonePrice>(
10
+ ({ sequence, onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/standalone-prices",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ key: `standalone-price-${sequence}`,
23
+ sku: `sku-${sequence}`,
24
+ value: {
25
+ centAmount: 1000,
26
+ currencyCode: "EUR",
27
+ },
28
+ active: true,
29
+ };
30
+ },
31
+ );
@@ -0,0 +1,21 @@
1
+ import type { State, StateDraft } from "@commercetools/platform-sdk";
2
+ import { Factory } from "fishery";
3
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
4
+
5
+ export const stateDraftFactory = (m: CommercetoolsMock) =>
6
+ Factory.define<StateDraft, StateDraft, State>(({ sequence, onCreate }) => {
7
+ onCreate(async (draft) => {
8
+ const response = await m.app.inject({
9
+ method: "POST",
10
+ url: "/dummy/states",
11
+ payload: draft,
12
+ });
13
+
14
+ return response.json();
15
+ });
16
+
17
+ return {
18
+ key: `state-${sequence}`,
19
+ type: "PaymentState",
20
+ };
21
+ });
@@ -0,0 +1,26 @@
1
+ import type { Store, StoreDraft } from "@commercetools/platform-sdk";
2
+ import { Factory } from "fishery";
3
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
4
+
5
+ export const storeDraftFactory = (m: CommercetoolsMock) =>
6
+ Factory.define<StoreDraft, StoreDraft, Store>(({ sequence, onCreate }) => {
7
+ onCreate(async (draft) => {
8
+ const response = await m.app.inject({
9
+ method: "POST",
10
+ url: "/dummy/stores",
11
+ payload: draft,
12
+ });
13
+
14
+ return response.json();
15
+ });
16
+
17
+ return {
18
+ key: `store-${sequence}`,
19
+ name: { en: `Store ${sequence}` },
20
+ languages: [],
21
+ countries: [],
22
+ distributionChannels: [],
23
+ supplyChannels: [],
24
+ productSelections: [],
25
+ };
26
+ });
@@ -0,0 +1,38 @@
1
+ import type {
2
+ Subscription,
3
+ SubscriptionDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const subscriptionDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<SubscriptionDraft, SubscriptionDraft, Subscription>(
10
+ ({ sequence, onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/subscriptions",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ key: `subscription-${sequence}`,
23
+ destination: {
24
+ type: "SQS",
25
+ queueUrl: `https://sqs.us-east-1.amazonaws.com/123456789/queue-${sequence}`,
26
+ accessKey: "AKIAIOSFODNN7EXAMPLE",
27
+ accessSecret: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
28
+ region: "us-east-1",
29
+ },
30
+ messages: [
31
+ {
32
+ resourceTypeId: "order",
33
+ types: ["OrderCreated"],
34
+ },
35
+ ],
36
+ };
37
+ },
38
+ );
@@ -0,0 +1,27 @@
1
+ import type {
2
+ TaxCategory,
3
+ TaxCategoryDraft,
4
+ } from "@commercetools/platform-sdk";
5
+ import { Factory } from "fishery";
6
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
7
+
8
+ export const taxCategoryDraftFactory = (m: CommercetoolsMock) =>
9
+ Factory.define<TaxCategoryDraft, TaxCategoryDraft, TaxCategory>(
10
+ ({ sequence, onCreate }) => {
11
+ onCreate(async (draft) => {
12
+ const response = await m.app.inject({
13
+ method: "POST",
14
+ url: "/dummy/tax-categories",
15
+ payload: draft,
16
+ });
17
+
18
+ return response.json();
19
+ });
20
+
21
+ return {
22
+ key: `tax-category-${sequence}`,
23
+ name: `Tax Category ${sequence}`,
24
+ rates: [],
25
+ };
26
+ },
27
+ );
@@ -1,19 +1,22 @@
1
1
  import type { Type, TypeDraft } from "@commercetools/platform-sdk";
2
2
  import { Factory } from "fishery";
3
- import supertest from "supertest";
4
3
  import type { CommercetoolsMock } from "#src/ctMock.ts";
5
4
 
6
5
  export const typeDraftFactory = (m: CommercetoolsMock) =>
7
- Factory.define<TypeDraft, TypeDraft, Type>(({ onCreate }) => {
6
+ Factory.define<TypeDraft, TypeDraft, Type>(({ sequence, onCreate }) => {
8
7
  onCreate(async (draft) => {
9
- const response = await supertest(m.app).post("/dummy/types").send(draft);
8
+ const response = await m.app.inject({
9
+ method: "POST",
10
+ url: "/dummy/types",
11
+ payload: draft,
12
+ });
10
13
 
11
- return response.body;
14
+ return response.json();
12
15
  });
13
16
 
14
17
  return {
15
- key: "type",
16
- name: { en: "Type Name" },
18
+ key: `type-${sequence}`,
19
+ name: { en: `Type Name ${sequence}` },
17
20
  resourceTypeIds: ["product"],
18
21
  description: { en: "Type description" },
19
22
  };
@@ -0,0 +1,22 @@
1
+ import type { Zone, ZoneDraft } from "@commercetools/platform-sdk";
2
+ import { Factory } from "fishery";
3
+ import type { CommercetoolsMock } from "#src/ctMock.ts";
4
+
5
+ export const zoneDraftFactory = (m: CommercetoolsMock) =>
6
+ Factory.define<ZoneDraft, ZoneDraft, Zone>(({ sequence, onCreate }) => {
7
+ onCreate(async (draft) => {
8
+ const response = await m.app.inject({
9
+ method: "POST",
10
+ url: "/dummy/zones",
11
+ payload: draft,
12
+ });
13
+
14
+ return response.json();
15
+ });
16
+
17
+ return {
18
+ key: `zone-${sequence}`,
19
+ name: `Zone ${sequence}`,
20
+ locations: [{ country: "NL" }],
21
+ };
22
+ });
@@ -0,0 +1,122 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { z } from "zod";
3
+ import { formatDetailedErrorMessage } from "./validate.ts";
4
+
5
+ describe("formatDetailedErrorMessage", () => {
6
+ it("formats missing required field", () => {
7
+ const schema = z.object({ name: z.string() });
8
+ const result = schema.safeParse({});
9
+ expect(result.success).toBe(false);
10
+ if (!result.success) {
11
+ expect(formatDetailedErrorMessage(result.error)).toBe(
12
+ "name: Missing required value",
13
+ );
14
+ }
15
+ });
16
+
17
+ it("formats wrong type (string expected, got number)", () => {
18
+ const schema = z.object({ name: z.string() });
19
+ const result = schema.safeParse({ name: 123 });
20
+ expect(result.success).toBe(false);
21
+ if (!result.success) {
22
+ expect(formatDetailedErrorMessage(result.error)).toBe(
23
+ "name: JSON String expected.",
24
+ );
25
+ }
26
+ });
27
+
28
+ it("formats wrong type (number expected, got string)", () => {
29
+ const schema = z.object({ count: z.number() });
30
+ const result = schema.safeParse({ count: "abc" });
31
+ expect(result.success).toBe(false);
32
+ if (!result.success) {
33
+ expect(formatDetailedErrorMessage(result.error)).toBe(
34
+ "count: JSON Number expected.",
35
+ );
36
+ }
37
+ });
38
+
39
+ it("formats wrong type (boolean expected)", () => {
40
+ const schema = z.object({ active: z.boolean() });
41
+ const result = schema.safeParse({ active: "yes" });
42
+ expect(result.success).toBe(false);
43
+ if (!result.success) {
44
+ expect(formatDetailedErrorMessage(result.error)).toBe(
45
+ "active: JSON Boolean expected.",
46
+ );
47
+ }
48
+ });
49
+
50
+ it("formats wrong type (object expected)", () => {
51
+ const schema = z.object({ data: z.object({ id: z.string() }) });
52
+ const result = schema.safeParse({ data: "not-an-object" });
53
+ expect(result.success).toBe(false);
54
+ if (!result.success) {
55
+ expect(formatDetailedErrorMessage(result.error)).toBe(
56
+ "data: JSON object expected.",
57
+ );
58
+ }
59
+ });
60
+
61
+ it("formats wrong type (array expected)", () => {
62
+ const schema = z.object({ items: z.array(z.string()) });
63
+ const result = schema.safeParse({ items: "not-an-array" });
64
+ expect(result.success).toBe(false);
65
+ if (!result.success) {
66
+ expect(formatDetailedErrorMessage(result.error)).toBe(
67
+ "items: JSON Array expected.",
68
+ );
69
+ }
70
+ });
71
+
72
+ it("formats invalid enum value", () => {
73
+ const schema = z.object({ role: z.enum(["Admin", "User"]) });
74
+ const result = schema.safeParse({ role: "SuperAdmin" });
75
+ expect(result.success).toBe(false);
76
+ if (!result.success) {
77
+ expect(formatDetailedErrorMessage(result.error)).toBe(
78
+ "role: Invalid enum value. Expected one of: 'Admin', 'User'",
79
+ );
80
+ }
81
+ });
82
+
83
+ it("formats nested field errors with dot path", () => {
84
+ const schema = z.object({
85
+ address: z.object({ country: z.string() }),
86
+ });
87
+ const result = schema.safeParse({ address: { country: 123 } });
88
+ expect(result.success).toBe(false);
89
+ if (!result.success) {
90
+ expect(formatDetailedErrorMessage(result.error)).toBe(
91
+ "address.country: JSON String expected.",
92
+ );
93
+ }
94
+ });
95
+
96
+ it("formats refine errors (custom code)", () => {
97
+ const schema = z
98
+ .object({ id: z.string().optional(), key: z.string().optional() })
99
+ .refine((data) => data.id !== undefined || data.key !== undefined, {
100
+ message: "Either 'id' or 'key' must be provided",
101
+ });
102
+ const result = schema.safeParse({});
103
+ expect(result.success).toBe(false);
104
+ if (!result.success) {
105
+ expect(formatDetailedErrorMessage(result.error)).toBe(
106
+ "Either 'id' or 'key' must be provided",
107
+ );
108
+ }
109
+ });
110
+
111
+ it("uses first issue only when multiple errors exist", () => {
112
+ const schema = z.object({ a: z.string(), b: z.number() });
113
+ const result = schema.safeParse({});
114
+ expect(result.success).toBe(false);
115
+ if (!result.success) {
116
+ // Should report the first missing field only
117
+ expect(formatDetailedErrorMessage(result.error)).toBe(
118
+ "a: Missing required value",
119
+ );
120
+ }
121
+ });
122
+ });
package/src/validate.ts CHANGED
@@ -1,18 +1,89 @@
1
1
  import type { InvalidJsonInputError } from "@commercetools/platform-sdk";
2
2
  import type { z } from "zod";
3
- import { fromZodError } from "zod-validation-error";
4
3
  import { CommercetoolsError } from "./exceptions.ts";
5
4
 
6
- export const validateData = <T>(data: any, schema: z.AnyZodObject) => {
7
- try {
8
- schema.parse(data);
5
+ /**
6
+ * Format a Zod error into a commercetools-style detailedErrorMessage.
7
+ *
8
+ * The real API uses messages like:
9
+ * "quantityOnStock: Missing required value"
10
+ * "name: JSON object expected."
11
+ * "roles: Invalid enum value. Expected one of: 'InventorySupply', ..."
12
+ *
13
+ * We use the first issue only, matching the real API behaviour of reporting
14
+ * a single detailed message.
15
+ */
16
+ export function formatDetailedErrorMessage(error: z.ZodError): string {
17
+ const issue = error.issues[0];
18
+ if (!issue) return "Unknown error";
19
+
20
+ const path = issue.path.join(".");
21
+
22
+ // Missing required field: Zod reports invalid_type with "received undefined"
23
+ if (
24
+ issue.code === "invalid_type" &&
25
+ issue.message.includes("received undefined")
26
+ ) {
27
+ return `${path}: Missing required value`;
28
+ }
29
+
30
+ // Wrong type (e.g. string received instead of number)
31
+ if (issue.code === "invalid_type") {
32
+ const expected = (issue as any).expected;
33
+ switch (expected) {
34
+ case "string":
35
+ return `${path}: JSON String expected.`;
36
+ case "number":
37
+ case "integer":
38
+ return `${path}: JSON Number expected.`;
39
+ case "boolean":
40
+ return `${path}: JSON Boolean expected.`;
41
+ case "object":
42
+ return `${path}: JSON object expected.`;
43
+ case "array":
44
+ return `${path}: JSON Array expected.`;
45
+ default:
46
+ return `${path}: Invalid type: expected ${expected}`;
47
+ }
48
+ }
49
+
50
+ // Invalid enum value
51
+ if (issue.code === "invalid_value") {
52
+ const values = (issue as any).values;
53
+ if (Array.isArray(values)) {
54
+ const formatted = values.map((v: string) => `'${v}'`).join(", ");
55
+ return `${path}: Invalid enum value. Expected one of: ${formatted}`;
56
+ }
57
+ }
58
+
59
+ // Refine errors (e.g. ResourceIdentifier id-or-key check)
60
+ if (issue.code === "custom") {
61
+ return issue.message;
62
+ }
63
+
64
+ // Fallback: use Zod's message with path prefix
65
+ return path ? `${path}: ${issue.message}` : issue.message;
66
+ }
67
+
68
+ export const validateData = <T>(data: any, schema: z.ZodType) => {
69
+ const result = schema.safeParse(data);
70
+ if (result.success) {
9
71
  return data as T;
10
- } catch (err: any) {
11
- const validationError = fromZodError(err);
72
+ }
73
+ throw new CommercetoolsError<InvalidJsonInputError>({
74
+ code: "InvalidJsonInput",
75
+ message: "Request body does not contain valid JSON.",
76
+ detailedErrorMessage: formatDetailedErrorMessage(result.error),
77
+ });
78
+ };
79
+
80
+ export const validateDraft = (data: unknown, schema: z.ZodType): void => {
81
+ const result = schema.safeParse(data);
82
+ if (!result.success) {
12
83
  throw new CommercetoolsError<InvalidJsonInputError>({
13
84
  code: "InvalidJsonInput",
14
85
  message: "Request body does not contain valid JSON.",
15
- detailedErrorMessage: validationError.toString(),
86
+ detailedErrorMessage: formatDetailedErrorMessage(result.error),
16
87
  });
17
88
  }
18
89
  };
package/src/.env DELETED
File without changes