@reactionary/source 0.3.18 → 0.6.2

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 (191) hide show
  1. package/README.md +28 -14
  2. package/core/src/client/client-builder.ts +54 -6
  3. package/core/src/factories/cart.factory.ts +40 -0
  4. package/core/src/factories/category.factory.ts +40 -0
  5. package/core/src/factories/checkout.factory.ts +59 -0
  6. package/core/src/factories/identity.factory.ts +26 -0
  7. package/core/src/factories/index.ts +15 -0
  8. package/core/src/factories/inventory.factory.ts +26 -0
  9. package/core/src/factories/order-search.factory.ts +33 -0
  10. package/core/src/factories/order.factory.ts +21 -0
  11. package/core/src/factories/price.factory.ts +29 -0
  12. package/core/src/factories/product-associations.factory.ts +30 -0
  13. package/core/src/factories/product-list.factory.ts +82 -0
  14. package/core/src/factories/product-reviews.factory.ts +58 -0
  15. package/core/src/factories/product-search.factory.ts +31 -0
  16. package/core/src/factories/product.factory.ts +21 -0
  17. package/core/src/factories/profile.factory.ts +23 -0
  18. package/core/src/factories/store.factory.ts +21 -0
  19. package/core/src/index.ts +3 -1
  20. package/core/src/providers/cart.provider.ts +12 -10
  21. package/core/src/providers/category.provider.ts +9 -7
  22. package/core/src/providers/checkout.provider.ts +14 -10
  23. package/core/src/providers/identity.provider.ts +7 -7
  24. package/core/src/providers/inventory.provider.ts +4 -4
  25. package/core/src/providers/order-search.provider.ts +4 -2
  26. package/core/src/providers/order.provider.ts +4 -4
  27. package/core/src/providers/price.provider.ts +5 -5
  28. package/core/src/providers/product-associations.provider.ts +6 -4
  29. package/core/src/providers/product-list.provider.ts +13 -8
  30. package/core/src/providers/product-reviews.provider.ts +8 -4
  31. package/core/src/providers/product-search.provider.ts +15 -28
  32. package/core/src/providers/product.provider.ts +6 -6
  33. package/core/src/providers/profile.provider.ts +8 -8
  34. package/core/src/providers/store.provider.ts +2 -2
  35. package/core/src/test/client-builder.spec.ts +81 -0
  36. package/examples/node/package.json +7 -7
  37. package/examples/node/src/basic/basic-node-provider-model-extension.spec.ts +10 -4
  38. package/examples/node/src/basic/basic-node-provider-query-extension.spec.ts +8 -2
  39. package/examples/node/src/basic/basic-node-setup.spec.ts +5 -1
  40. package/examples/node/src/basic/client-creation.spec.ts +3 -3
  41. package/examples/node/src/utils.ts +41 -41
  42. package/examples/node/tsconfig.lib.json +2 -1
  43. package/package.json +1 -1
  44. package/providers/algolia/src/core/initialize.ts +76 -21
  45. package/providers/algolia/src/core/initialize.types.ts +107 -0
  46. package/providers/algolia/src/factories/index.ts +1 -0
  47. package/providers/algolia/src/factories/product-search/product-search.factory.ts +182 -0
  48. package/providers/algolia/src/index.ts +2 -2
  49. package/providers/algolia/src/providers/analytics.provider.ts +4 -4
  50. package/providers/algolia/src/providers/product-search.provider.ts +67 -184
  51. package/providers/algolia/src/schema/capabilities.schema.ts +81 -7
  52. package/providers/algolia/src/test/analytics.spec.ts +9 -1
  53. package/providers/algolia/src/test/client-builder-product-search-extension.example.ts +85 -0
  54. package/providers/commercetools/src/core/capability-descriptors.ts +324 -0
  55. package/providers/commercetools/src/core/initialize.ts +35 -151
  56. package/providers/commercetools/src/core/initialize.types.ts +174 -0
  57. package/providers/commercetools/src/factories/cart/cart.factory.ts +142 -0
  58. package/providers/commercetools/src/factories/category/category.factory.ts +77 -0
  59. package/providers/commercetools/src/factories/checkout/checkout-initializer-overrides.example.ts +94 -0
  60. package/providers/commercetools/src/factories/checkout/checkout.factory.ts +338 -0
  61. package/providers/commercetools/src/factories/identity/identity.factory.ts +26 -0
  62. package/providers/commercetools/src/factories/inventory/inventory.factory.ts +49 -0
  63. package/providers/commercetools/src/factories/order/order.factory.ts +149 -0
  64. package/providers/commercetools/src/factories/order-search/order-search.factory.ts +108 -0
  65. package/providers/commercetools/src/factories/price/price.factory.ts +76 -0
  66. package/providers/commercetools/src/factories/product/product-factory-baseline.example.ts +14 -0
  67. package/providers/commercetools/src/factories/product/product-factory-schema-and-parse-extension.example.ts +35 -0
  68. package/providers/commercetools/src/factories/product/product-factory-schema-extension.example.ts +23 -0
  69. package/providers/commercetools/src/factories/product/product-initializer-factory-extension.example.ts +41 -0
  70. package/providers/commercetools/src/factories/product/product-provider-custom-method-only.example.ts +47 -0
  71. package/providers/commercetools/src/factories/product/product-provider-schema-signature-extension.example.ts +61 -0
  72. package/providers/commercetools/src/factories/product/product.factory.ts +220 -0
  73. package/providers/commercetools/src/factories/product/utils.example.ts +9 -0
  74. package/providers/commercetools/src/factories/product-associations/product-associations.factory.ts +103 -0
  75. package/providers/commercetools/src/factories/product-list/product-list.factory.ts +122 -0
  76. package/providers/commercetools/src/factories/product-reviews/product-reviews.factory.ts +81 -0
  77. package/providers/commercetools/src/factories/product-search/product-search.factory.ts +182 -0
  78. package/providers/commercetools/src/factories/profile/profile.factory.ts +94 -0
  79. package/providers/commercetools/src/factories/store/store.factory.ts +49 -0
  80. package/providers/commercetools/src/index.ts +15 -0
  81. package/providers/commercetools/src/providers/cart.provider.ts +67 -193
  82. package/providers/commercetools/src/providers/category.provider.ts +24 -64
  83. package/providers/commercetools/src/providers/checkout.provider.ts +50 -322
  84. package/providers/commercetools/src/providers/identity.provider.ts +35 -15
  85. package/providers/commercetools/src/providers/inventory.provider.ts +13 -31
  86. package/providers/commercetools/src/providers/order-search.provider.ts +16 -110
  87. package/providers/commercetools/src/providers/order.provider.ts +13 -144
  88. package/providers/commercetools/src/providers/price.provider.ts +37 -51
  89. package/providers/commercetools/src/providers/product-associations.provider.ts +39 -104
  90. package/providers/commercetools/src/providers/product-list.provider.ts +38 -23
  91. package/providers/commercetools/src/providers/product-reviews.provider.ts +34 -14
  92. package/providers/commercetools/src/providers/product-search.provider.ts +17 -170
  93. package/providers/commercetools/src/providers/product.provider.ts +20 -199
  94. package/providers/commercetools/src/providers/profile.provider.ts +27 -73
  95. package/providers/commercetools/src/providers/store.provider.ts +13 -31
  96. package/providers/commercetools/src/schema/capabilities.schema.ts +258 -20
  97. package/providers/commercetools/src/test/caching.spec.ts +18 -2
  98. package/providers/commercetools/src/test/client-builder-merge-extensions.example.ts +125 -0
  99. package/providers/fake/src/core/initialize.ts +213 -44
  100. package/providers/fake/src/core/initialize.types.ts +164 -0
  101. package/providers/fake/src/factories/cart/cart.factory.ts +34 -0
  102. package/providers/fake/src/factories/category/category.factory.ts +40 -0
  103. package/providers/fake/src/factories/checkout/checkout.factory.ts +53 -0
  104. package/providers/fake/src/factories/identity/identity.factory.ts +25 -0
  105. package/providers/fake/src/factories/index.ts +14 -0
  106. package/providers/fake/src/factories/inventory/inventory.factory.ts +25 -0
  107. package/providers/fake/src/factories/order/order.factory.ts +22 -0
  108. package/providers/fake/src/factories/order-search/order-search.factory.ts +27 -0
  109. package/providers/fake/src/factories/price/price.factory.ts +26 -0
  110. package/providers/fake/src/factories/product/product.factory.ts +22 -0
  111. package/providers/fake/src/factories/product-associations/product-associations.factory.ts +25 -0
  112. package/providers/fake/src/factories/product-reviews/product-reviews.factory.ts +53 -0
  113. package/providers/fake/src/factories/product-search/product-search.factory.ts +27 -0
  114. package/providers/fake/src/factories/profile/profile.factory.ts +22 -0
  115. package/providers/fake/src/factories/store/store.factory.ts +22 -0
  116. package/providers/fake/src/index.ts +2 -0
  117. package/providers/fake/src/providers/cart.provider.ts +23 -14
  118. package/providers/fake/src/providers/category.provider.ts +120 -105
  119. package/providers/fake/src/providers/checkout.provider.ts +39 -20
  120. package/providers/fake/src/providers/identity.provider.ts +40 -34
  121. package/providers/fake/src/providers/inventory.provider.ts +26 -24
  122. package/providers/fake/src/providers/order-search.provider.ts +38 -30
  123. package/providers/fake/src/providers/order.provider.ts +21 -37
  124. package/providers/fake/src/providers/price.provider.ts +42 -34
  125. package/providers/fake/src/providers/product-associations.provider.ts +23 -10
  126. package/providers/fake/src/providers/product-reviews.provider.ts +71 -69
  127. package/providers/fake/src/providers/product-search.provider.ts +43 -70
  128. package/providers/fake/src/providers/product.provider.ts +34 -32
  129. package/providers/fake/src/providers/profile.provider.ts +62 -55
  130. package/providers/fake/src/providers/store.provider.ts +38 -22
  131. package/providers/fake/src/schema/capabilities.schema.ts +175 -18
  132. package/providers/fake/src/test/cart.provider.spec.ts +20 -3
  133. package/providers/fake/src/test/category.provider.spec.ts +4 -1
  134. package/providers/fake/src/test/checkout.provider.spec.ts +12 -2
  135. package/providers/fake/src/test/client-builder-product-extension.example.ts +75 -0
  136. package/providers/fake/src/test/order-search.provider.spec.ts +4 -7
  137. package/providers/fake/src/test/order.provider.spec.ts +4 -6
  138. package/providers/fake/src/test/price.provider.spec.ts +3 -1
  139. package/providers/fake/src/test/product.provider.spec.ts +8 -2
  140. package/providers/fake/src/test/profile.provider.spec.ts +4 -2
  141. package/providers/google-analytics/src/core/initialize.ts +37 -12
  142. package/providers/google-analytics/src/core/initialize.types.ts +47 -0
  143. package/providers/google-analytics/src/index.ts +1 -0
  144. package/providers/google-analytics/src/schema/capabilities.schema.ts +31 -5
  145. package/providers/medusa/src/core/initialize.ts +324 -81
  146. package/providers/medusa/src/core/initialize.types.ts +184 -0
  147. package/providers/medusa/src/factories/cart/cart.factory.ts +34 -0
  148. package/providers/medusa/src/factories/category/category.factory.ts +37 -0
  149. package/providers/medusa/src/factories/checkout/checkout.factory.ts +50 -0
  150. package/providers/medusa/src/factories/identity/identity.factory.ts +22 -0
  151. package/providers/medusa/src/factories/index.ts +12 -0
  152. package/providers/medusa/src/factories/inventory/inventory.factory.ts +25 -0
  153. package/providers/medusa/src/factories/order/order.factory.ts +22 -0
  154. package/providers/medusa/src/factories/order-search/order-search.factory.ts +27 -0
  155. package/providers/medusa/src/factories/price/price.factory.ts +26 -0
  156. package/providers/medusa/src/factories/product/product.factory.ts +22 -0
  157. package/providers/medusa/src/factories/product-associations/product-associations.factory.ts +25 -0
  158. package/providers/medusa/src/factories/product-search/product-search.factory.ts +27 -0
  159. package/providers/medusa/src/factories/profile/profile.factory.ts +22 -0
  160. package/providers/medusa/src/index.ts +2 -0
  161. package/providers/medusa/src/providers/cart.provider.ts +33 -20
  162. package/providers/medusa/src/providers/category.provider.ts +30 -12
  163. package/providers/medusa/src/providers/checkout.provider.ts +42 -17
  164. package/providers/medusa/src/providers/identity.provider.ts +1 -1
  165. package/providers/medusa/src/providers/inventory.provider.ts +21 -7
  166. package/providers/medusa/src/providers/order-search.provider.ts +16 -5
  167. package/providers/medusa/src/providers/order.provider.ts +17 -5
  168. package/providers/medusa/src/providers/price.provider.ts +26 -7
  169. package/providers/medusa/src/providers/product-associations.provider.ts +19 -8
  170. package/providers/medusa/src/providers/product-search.provider.ts +19 -31
  171. package/providers/medusa/src/providers/product.provider.ts +47 -11
  172. package/providers/medusa/src/providers/profile.provider.ts +35 -11
  173. package/providers/medusa/src/schema/capabilities.schema.ts +229 -18
  174. package/providers/medusa/src/test/cart.provider.spec.ts +18 -2
  175. package/providers/medusa/src/test/category.provider.spec.ts +4 -1
  176. package/providers/medusa/src/test/checkout.spec.ts +9 -9
  177. package/providers/medusa/src/test/inventory.provider.spec.ts +3 -1
  178. package/providers/medusa/src/test/large-cart.provider.spec.ts +8 -2
  179. package/providers/medusa/src/test/price.provider.spec.ts +8 -1
  180. package/providers/medusa/src/test/product.provider.spec.ts +3 -1
  181. package/providers/medusa/src/test/search.provider.spec.ts +16 -3
  182. package/providers/meilisearch/src/core/initialize.ts +88 -21
  183. package/providers/meilisearch/src/core/initialize.types.ts +119 -0
  184. package/providers/meilisearch/src/factories/index.ts +2 -0
  185. package/providers/meilisearch/src/factories/order-search/order-search.factory.ts +27 -0
  186. package/providers/meilisearch/src/factories/product-search/product-search.factory.ts +27 -0
  187. package/providers/meilisearch/src/index.ts +2 -0
  188. package/providers/meilisearch/src/providers/index.ts +1 -0
  189. package/providers/meilisearch/src/providers/order-search.provider.ts +21 -6
  190. package/providers/meilisearch/src/providers/product-search.provider.ts +24 -8
  191. package/providers/meilisearch/src/schema/capabilities.schema.ts +95 -8
@@ -1,10 +1,12 @@
1
- import type { Address as CTAddress, Cart as CTCart, Payment as CTPayment, ShippingMethod as CTShippingMethod, LineItem, MyCartUpdateAction } from '@commercetools/platform-sdk';
1
+ import type { MyCartUpdateAction } from '@commercetools/platform-sdk';
2
2
  import type {
3
- Address,
4
3
  Cache,
5
- Checkout,
4
+ CheckoutFactory,
5
+ CheckoutFactoryCheckoutOutput,
6
+ CheckoutFactoryPaymentMethodOutput,
7
+ CheckoutFactoryShippingMethodOutput,
8
+ CheckoutFactoryWithOutput,
6
9
  CheckoutIdentifier,
7
- CheckoutItem,
8
10
  CheckoutMutationAddPaymentInstruction,
9
11
  CheckoutMutationFinalizeCheckout,
10
12
  CheckoutMutationInitiateCheckout,
@@ -14,23 +16,12 @@ import type {
14
16
  CheckoutQueryById,
15
17
  CheckoutQueryForAvailablePaymentMethods,
16
18
  CheckoutQueryForAvailableShippingMethods,
17
- CostBreakDown,
18
- Currency,
19
- MonetaryAmount,
20
19
  NotFoundError,
21
- PaymentInstruction,
22
- PaymentInstructionIdentifier,
23
20
  PaymentMethod,
24
- PaymentMethodIdentifier,
25
- PaymentStatus,
26
21
  RequestContext,
27
22
  Result,
28
- ShippingInstruction,
29
- ShippingMethod,
30
- ShippingMethodIdentifier,
31
23
  } from '@reactionary/core';
32
24
  import {
33
- CheckoutItemSchema,
34
25
  CheckoutMutationAddPaymentInstructionSchema,
35
26
  CheckoutMutationFinalizeCheckoutSchema,
36
27
  CheckoutMutationInitiateCheckoutSchema,
@@ -51,11 +42,9 @@ import {
51
42
  } from '@reactionary/core';
52
43
  import * as z from 'zod';
53
44
  import type { CommercetoolsAPI } from '../core/client.js';
54
- import {
55
- type CommercetoolsCartIdentifier,
56
- type CommercetoolsCheckoutIdentifier,
57
- } from '../schema/commercetools.schema.js';
45
+ import { type CommercetoolsCheckoutIdentifier } from '../schema/commercetools.schema.js';
58
46
  import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
47
+ import type { CommercetoolsCheckoutFactory } from '../factories/checkout/checkout.factory.js';
59
48
 
60
49
  export class CheckoutNotReadyForFinalizationError extends Error {
61
50
  constructor(public checkoutIdentifier: CheckoutIdentifier) {
@@ -69,20 +58,29 @@ export class CheckoutNotReadyForFinalizationError extends Error {
69
58
  }
70
59
  }
71
60
 
72
- export class CommercetoolsCheckoutProvider extends CheckoutProvider {
61
+ export class CommercetoolsCheckoutProvider<
62
+ TFactory extends CheckoutFactory = CommercetoolsCheckoutFactory,
63
+ > extends CheckoutProvider<
64
+ CheckoutFactoryCheckoutOutput<TFactory>,
65
+ CheckoutFactoryShippingMethodOutput<TFactory>,
66
+ CheckoutFactoryPaymentMethodOutput<TFactory>
67
+ > {
73
68
  protected config: CommercetoolsConfiguration;
74
69
  protected commercetools: CommercetoolsAPI;
70
+ protected factory: CheckoutFactoryWithOutput<TFactory>;
75
71
 
76
72
  constructor(
77
73
  config: CommercetoolsConfiguration,
78
74
  cache: Cache,
79
75
  context: RequestContext,
80
- commercetools: CommercetoolsAPI
76
+ commercetools: CommercetoolsAPI,
77
+ factory: CheckoutFactoryWithOutput<TFactory>,
81
78
  ) {
82
79
  super(cache, context);
83
80
 
84
81
  this.config = config;
85
82
  this.commercetools = commercetools;
83
+ this.factory = factory;
86
84
  }
87
85
 
88
86
  protected async getClient() {
@@ -113,7 +111,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
113
111
  })
114
112
  public async initiateCheckoutForCart(
115
113
  payload: CheckoutMutationInitiateCheckout
116
- ): Promise<Result<Checkout>> {
114
+ ): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>> {
117
115
  // so......we could copy the cart......
118
116
 
119
117
  const client = await this.getClient();
@@ -187,14 +185,14 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
187
185
  })
188
186
  .execute();
189
187
 
190
- return success(this.parseSingle(checkoutResponse.body));
188
+ return success(this.factory.parseCheckout(this.context, checkoutResponse.body));
191
189
  }
192
190
 
193
191
  @Reactionary({
194
192
  inputSchema: CheckoutQueryByIdSchema,
195
193
  outputSchema: CheckoutSchema.nullable(),
196
194
  })
197
- public async getById(payload: CheckoutQueryById): Promise<Result<Checkout, NotFoundError>> {
195
+ public async getById(payload: CheckoutQueryById): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>, NotFoundError>> {
198
196
  const client = await this.getClient();
199
197
  const checkoutResponse = await client.carts
200
198
  .withId({ ID: payload.identifier.key })
@@ -205,7 +203,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
205
203
  })
206
204
  .execute();
207
205
 
208
- const checkout = this.parseSingle(checkoutResponse.body);
206
+ const checkout = this.factory.parseCheckout(this.context, checkoutResponse.body);
209
207
 
210
208
  if (checkoutResponse.body.cartState === 'Ordered') {
211
209
  const order = await client.orders
@@ -230,7 +228,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
230
228
  })
231
229
  public async setShippingAddress(
232
230
  payload: CheckoutMutationSetShippingAddress
233
- ): Promise<Result<Checkout>> {
231
+ ): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>> {
234
232
  const client = await this.getClient();
235
233
 
236
234
  const version = (payload.checkout as CommercetoolsCheckoutIdentifier)
@@ -258,7 +256,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
258
256
  })
259
257
  .execute();
260
258
 
261
- return success(this.parseSingle(checkoutResponse.body));
259
+ return success(this.factory.parseCheckout(this.context, checkoutResponse.body));
262
260
  }
263
261
 
264
262
  @Reactionary({
@@ -267,7 +265,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
267
265
  })
268
266
  public async getAvailableShippingMethods(
269
267
  payload: CheckoutQueryForAvailableShippingMethods
270
- ): Promise<Result<ShippingMethod[]>> {
268
+ ): Promise<Result<CheckoutFactoryShippingMethodOutput<TFactory>[]>> {
271
269
  const client = await this.getClient();
272
270
  const shippingMethodsResponse = await client.shippingMethods
273
271
  .matchingCart()
@@ -278,33 +276,10 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
278
276
  })
279
277
  .execute();
280
278
 
281
- const result: Array<ShippingMethod> = [];
282
- const inputShippingMethods: CTShippingMethod[] = shippingMethodsResponse
283
- .body.results as CTShippingMethod[];
284
- for (const sm of inputShippingMethods) {
285
- const identifier = {
286
- key: sm.key!,
287
- } satisfies ShippingMethodIdentifier;
288
- const name = sm.name;
289
- const description = sm.localizedDescription?.[this.context.languageContext.locale] || '';
290
- const shippingMethod = {
291
- deliveryTime: '',
292
- description,
293
- identifier,
294
- name,
295
- price: sm.zoneRates[0].shippingRates[0].price
296
- ? {
297
- value:
298
- (sm.zoneRates[0].shippingRates[0].price.centAmount || 0) / 100,
299
- currency:
300
- sm.zoneRates[0].shippingRates[0].price.currencyCode as Currency ||
301
- this.context.languageContext.currencyCode,
302
- }
303
- : { value: 0, currency: this.context.languageContext.currencyCode },
304
- } satisfies ShippingMethod;
279
+ const result = shippingMethodsResponse.body.results.map((shippingMethod) =>
280
+ this.factory.parseShippingMethod(this.context, shippingMethod),
281
+ );
305
282
 
306
- result.push(shippingMethod);
307
- }
308
283
  return success(result);
309
284
  }
310
285
 
@@ -314,7 +289,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
314
289
  })
315
290
  public async getAvailablePaymentMethods(
316
291
  payload: CheckoutQueryForAvailablePaymentMethods
317
- ): Promise<Result<PaymentMethod[]>> {
292
+ ): Promise<Result<CheckoutFactoryPaymentMethodOutput<TFactory>[]>> {
318
293
  // Commercetools does not have a concept of payment methods, as these are handled by the payment providers.
319
294
  // So for now, we will return an empty array.
320
295
  const staticMethods = this.getStaticPaymentMethods(payload.checkout);
@@ -322,7 +297,11 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
322
297
  const dynamicMethods: PaymentMethod[] = [];
323
298
  // later we will also fetch any stored payment methods the user has...
324
299
 
325
- return success([...staticMethods, ...dynamicMethods]);
300
+ const result = [...staticMethods, ...dynamicMethods].map((paymentMethod) =>
301
+ this.factory.parsePaymentMethod(this.context, paymentMethod),
302
+ );
303
+
304
+ return success(result);
326
305
  }
327
306
 
328
307
  @Reactionary({
@@ -331,7 +310,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
331
310
  })
332
311
  public async addPaymentInstruction(
333
312
  payload: CheckoutMutationAddPaymentInstruction
334
- ): Promise<Result<Checkout>> {
313
+ ): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>> {
335
314
  const client = await this.getClient();
336
315
 
337
316
  const response = await client.payments
@@ -391,7 +370,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
391
370
  })
392
371
  public async removePaymentInstruction(
393
372
  payload: CheckoutMutationRemovePaymentInstruction
394
- ): Promise<Result<Checkout>> {
373
+ ): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>> {
395
374
  const client = await this.getClient();
396
375
 
397
376
  // FIXME: Need to get full-endpoint rights, if we want to cancel the authorization on the payment. The MyPayment endpoint does not support
@@ -458,7 +437,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
458
437
  })
459
438
  public async setShippingInstruction(
460
439
  payload: CheckoutMutationSetShippingInstruction
461
- ): Promise<Result<Checkout>> {
440
+ ): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>> {
462
441
  const actions: MyCartUpdateAction[] = [];
463
442
  actions.push({
464
443
  action: 'setShippingMethod',
@@ -497,7 +476,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
497
476
  })
498
477
  public async finalizeCheckout(
499
478
  payload: CheckoutMutationFinalizeCheckout
500
- ): Promise<Result<Checkout>> {
479
+ ): Promise<Result<CheckoutFactoryCheckoutOutput<TFactory>>> {
501
480
  const checkout = await this.getById({ identifier: payload.checkout });
502
481
  if (!checkout.success || !checkout.value.readyForFinalization) {
503
482
  throw new CheckoutNotReadyForFinalizationError(payload.checkout);
@@ -507,7 +486,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
507
486
  const ctId = payload.checkout as CommercetoolsCheckoutIdentifier;
508
487
 
509
488
  // create the order from the cart
510
- const orderResponse = await client.orders
489
+ await client.orders
511
490
  .post({
512
491
  body: {
513
492
  id: ctId.key,
@@ -516,15 +495,21 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
516
495
  })
517
496
  .execute();
518
497
 
519
- return this.getById({
498
+ const result = await this.getById({
520
499
  identifier: payload.checkout,
521
- }) as unknown as Result<Checkout>;
500
+ });
501
+
502
+ if (!result.success) {
503
+ throw new Error('Unable to fetch checkout after finalization.');
504
+ }
505
+
506
+ return success(result.value);
522
507
  }
523
508
 
524
509
  protected async applyActions(
525
510
  checkout: CheckoutIdentifier,
526
511
  actions: MyCartUpdateAction[]
527
- ): Promise<Checkout> {
512
+ ): Promise<CheckoutFactoryCheckoutOutput<TFactory>> {
528
513
  const client = await this.getClient();
529
514
  const ctId = checkout as CommercetoolsCheckoutIdentifier;
530
515
 
@@ -546,7 +531,7 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
546
531
  console.error(response.error);
547
532
  }
548
533
 
549
- const p = this.parseSingle(response.body);
534
+ const p = this.factory.parseCheckout(this.context, response.body);
550
535
 
551
536
  return p;
552
537
  } catch (e: any) {
@@ -566,261 +551,4 @@ export class CommercetoolsCheckoutProvider extends CheckoutProvider {
566
551
  ): PaymentMethod[] {
567
552
  return this.config.paymentMethods || [];
568
553
  }
569
-
570
- protected parseCheckoutItem(remoteItem: LineItem): CheckoutItem {
571
- const unitPrice = remoteItem.price.value.centAmount;
572
- const totalPrice = remoteItem.totalPrice.centAmount || 0;
573
- const totalDiscount = remoteItem.price.discounted?.value.centAmount || 0;
574
- const unitDiscount = totalDiscount / remoteItem.quantity;
575
- const currency =
576
- remoteItem.price.value.currencyCode.toUpperCase() as Currency;
577
-
578
- const item = {
579
- identifier: {
580
- key: remoteItem.id,
581
- },
582
- variant: {
583
- sku: remoteItem.variant.sku || '',
584
- },
585
- quantity: remoteItem.quantity,
586
- price: {
587
- unitPrice: {
588
- value: unitPrice / 100,
589
- currency,
590
- },
591
- unitDiscount: {
592
- value: unitDiscount / 100,
593
- currency,
594
- },
595
- totalPrice: {
596
- value: (totalPrice || 0) / 100,
597
- currency,
598
- },
599
- totalDiscount: {
600
- value: totalDiscount / 100,
601
- currency,
602
- },
603
- },
604
- } satisfies CheckoutItem;
605
-
606
- return CheckoutItemSchema.parse(item);
607
- }
608
-
609
- protected parseSingle(remote: CTCart): Checkout {
610
- const identifier = {
611
- key: remote.id,
612
- version: remote.version || 0,
613
- } satisfies CommercetoolsCheckoutIdentifier;
614
-
615
- const originalCartReference = {
616
- key: remote.custom?.fields['commerceToolsCartId'] || '',
617
- version: 0,
618
- } satisfies CommercetoolsCartIdentifier;
619
-
620
- let shippingAddress: Address | undefined;
621
- if (remote.shippingAddress) {
622
- shippingAddress = this.parseAddress(remote.shippingAddress);
623
- }
624
-
625
- let billingAddress: Address | undefined;
626
- if (remote.billingAddress) {
627
- billingAddress = this.parseAddress(remote.billingAddress);
628
- }
629
-
630
- const paymentInstructions = new Array<PaymentInstruction>();
631
- for (const p of remote.paymentInfo?.payments || []) {
632
- if (p.obj) {
633
- paymentInstructions.push(this.parsePaymentInstruction(p.obj));
634
- }
635
- }
636
-
637
- const grandTotal = remote.totalPrice.centAmount || 0;
638
- const shippingTotal = remote.shippingInfo?.price.centAmount || 0;
639
- const productTotal = grandTotal - shippingTotal;
640
- const taxTotal = remote.taxedPrice?.totalTax?.centAmount || 0;
641
- const discountTotal =
642
- remote.discountOnTotalPrice?.discountedAmount.centAmount || 0;
643
- const surchargeTotal = 0;
644
- const currency = remote.totalPrice.currencyCode as Currency;
645
-
646
- const price = {
647
- totalTax: {
648
- value: taxTotal / 100,
649
- currency,
650
- },
651
- totalDiscount: {
652
- value: discountTotal / 100,
653
- currency,
654
- },
655
- totalSurcharge: {
656
- value: surchargeTotal / 100,
657
- currency,
658
- },
659
- totalShipping: {
660
- value: shippingTotal / 100,
661
- currency: currency
662
- },
663
- totalProductPrice: {
664
- value: productTotal / 100,
665
- currency,
666
- },
667
- grandTotal: {
668
- value: grandTotal / 100,
669
- currency,
670
- },
671
- } satisfies CostBreakDown;
672
-
673
- const items = new Array<CheckoutItem>();
674
- for (const remoteItem of remote.lineItems) {
675
- const item = this.parseCheckoutItem(remoteItem);
676
- items.push(item);
677
- }
678
-
679
- const shippingInstruction = this.parseShippingInstruction(remote);
680
- const readyForFinalization = this.isReadyForFinalization(
681
- price,
682
- paymentInstructions,
683
- billingAddress,
684
- shippingAddress,
685
- shippingInstruction
686
- );
687
-
688
- const result = {
689
- identifier,
690
- originalCartReference,
691
- name: remote.custom?.fields['name'] || '',
692
- description: remote.custom?.fields['description'] || '',
693
- readyForFinalization,
694
- billingAddress,
695
- shippingAddress,
696
- shippingInstruction,
697
- paymentInstructions,
698
- items,
699
- price,
700
- } satisfies Checkout;
701
-
702
- return result;
703
- }
704
-
705
- protected isReadyForFinalization(
706
- price: CostBreakDown,
707
- paymentInstructions: Array<PaymentInstruction>,
708
- billingAddress?: Address,
709
- shippingAddress?: Address,
710
- shippingInstruction?: ShippingInstruction
711
- ): boolean {
712
- // we should have a billing address
713
- if (!billingAddress) return false;
714
-
715
- // we should know how to ship it
716
- if (!shippingInstruction) return false;
717
-
718
- // and it should ship either to an address or a pickup point
719
- if (!shippingAddress && !shippingInstruction.pickupPoint) return false;
720
-
721
- // and it should be paid for
722
- if (paymentInstructions.length === 0) return false;
723
-
724
- const authorizedPayments = paymentInstructions
725
- .filter((pi) => pi.status === 'authorized')
726
- .map((x) => x.amount.value)
727
- .reduce((a, b) => a + b, 0);
728
- if (price.grandTotal.value !== authorizedPayments) return false;
729
-
730
- return true;
731
- }
732
-
733
- protected parsePaymentInstruction(remote: CTPayment): PaymentInstruction {
734
- const identifier = {
735
- key: remote.id,
736
- } satisfies PaymentInstructionIdentifier;
737
- const amount = {
738
- value: remote.amountPlanned.centAmount / 100,
739
- currency: remote.amountPlanned.currencyCode as Currency,
740
- } satisfies MonetaryAmount;
741
-
742
- const method = remote.paymentMethodInfo?.method || 'unknown';
743
- const paymentProcessor =
744
- remote.paymentMethodInfo?.paymentInterface || method;
745
- const paymentName =
746
- remote.paymentMethodInfo.name![this.context.languageContext.locale];
747
-
748
- const paymentMethod = {
749
- method,
750
- paymentProcessor,
751
- name: paymentName || method || 'Unknown',
752
- } satisfies PaymentMethodIdentifier;
753
-
754
- const customData = remote.custom?.fields || {};
755
- const protocolData =
756
- Object.keys(customData).map((x) => ({ key: x, value: customData[x] })) ||
757
- [];
758
-
759
- let status: PaymentStatus = 'pending';
760
- if (remote.transactions && remote.transactions.length > 0) {
761
- const lastTransaction =
762
- remote.transactions[remote.transactions.length - 1];
763
- if (
764
- lastTransaction.type === 'Authorization' &&
765
- lastTransaction.state === 'Pending'
766
- ) {
767
- status = 'pending';
768
- } else if (
769
- lastTransaction.type === 'Authorization' &&
770
- lastTransaction.state === 'Success'
771
- ) {
772
- status = 'authorized';
773
- }
774
- } else {
775
- status = 'pending';
776
- }
777
-
778
- const result = {
779
- amount,
780
- identifier,
781
- paymentMethod,
782
- protocolData,
783
- status
784
- } satisfies PaymentInstruction;
785
-
786
- return result;
787
- }
788
-
789
- protected parseAddress(remote: CTAddress) {
790
- return {
791
- countryCode: remote.country || '',
792
- firstName: remote.firstName || '',
793
- lastName: remote.lastName || '',
794
- streetAddress: remote.streetName || '',
795
- streetNumber: remote.streetNumber || '',
796
- postalCode: remote.postalCode || '',
797
- city: remote.city || '',
798
- identifier: {
799
- nickName: '',
800
- },
801
- region: '',
802
- } satisfies Address;
803
- }
804
-
805
- protected parseShippingInstruction(
806
- remote: CTCart
807
- ): ShippingInstruction | undefined {
808
- if (!remote.shippingInfo) return undefined;
809
-
810
- const instructions = remote.custom?.fields['shippingInstruction'] || '';
811
- const consentForUnattendedDelivery =
812
- remote.custom?.fields['consentForUnattendedDelivery'] === 'true' || false;
813
- const pickupPoint = remote.custom?.fields['pickupPointId'] || '';
814
-
815
- const shippingInstruction = {
816
- shippingMethod: {
817
- key: remote.shippingInfo.shippingMethod?.obj?.key || '',
818
- },
819
- pickupPoint: pickupPoint || '',
820
- instructions: instructions || '',
821
- consentForUnattendedDelivery: consentForUnattendedDelivery || false,
822
- } satisfies ShippingInstruction;
823
-
824
- return shippingInstruction;
825
- }
826
554
  }
@@ -1,5 +1,7 @@
1
1
  import {
2
- type Identity,
2
+ type IdentityFactory,
3
+ type IdentityFactoryOutput,
4
+ type IdentityFactoryWithOutput,
3
5
  type IdentityMutationLogin,
4
6
  type IdentityQuerySelf,
5
7
  type RequestContext,
@@ -16,29 +18,38 @@ import {
16
18
  } from '@reactionary/core';
17
19
  import type { CommercetoolsConfiguration } from '../schema/configuration.schema.js';
18
20
  import type { CommercetoolsAPI } from '../core/client.js';
21
+ import type { CommercetoolsIdentityFactory } from '../factories/identity/identity.factory.js';
19
22
 
20
- export class CommercetoolsIdentityProvider extends IdentityProvider {
23
+ export class CommercetoolsIdentityProvider<
24
+ TFactory extends IdentityFactory = CommercetoolsIdentityFactory,
25
+ > extends IdentityProvider<IdentityFactoryOutput<TFactory>> {
21
26
  protected config: CommercetoolsConfiguration;
22
27
  protected commercetools: CommercetoolsAPI;
28
+ protected factory: IdentityFactoryWithOutput<TFactory>;
23
29
 
24
30
  constructor(
25
31
  config: CommercetoolsConfiguration,
26
32
  cache: Cache,
27
33
  context: RequestContext,
28
- commercetools: CommercetoolsAPI
34
+ commercetools: CommercetoolsAPI,
35
+ factory: IdentityFactoryWithOutput<TFactory>,
29
36
  ) {
30
37
  super(cache, context);
31
38
 
32
39
  this.config = config;
33
40
  this.commercetools = commercetools;
41
+ this.factory = factory;
34
42
  }
35
43
 
36
44
  @Reactionary({
37
45
  inputSchema: IdentityQuerySelfSchema,
38
46
  outputSchema: IdentitySchema,
39
47
  })
40
- public override async getSelf(payload: IdentityQuerySelf): Promise<Result<Identity>> {
41
- const identity = await this.commercetools.introspect();
48
+ public override async getSelf(payload: IdentityQuerySelf): Promise<Result<IdentityFactoryOutput<TFactory>>> {
49
+ const identity = this.factory.parseIdentity(
50
+ this.context,
51
+ await this.commercetools.introspect(),
52
+ );
42
53
 
43
54
  this.updateIdentityContext(identity);
44
55
 
@@ -49,10 +60,13 @@ export class CommercetoolsIdentityProvider extends IdentityProvider {
49
60
  inputSchema: IdentityMutationLoginSchema,
50
61
  outputSchema: IdentitySchema,
51
62
  })
52
- public override async login(payload: IdentityMutationLogin): Promise<Result<Identity>> {
53
- const identity = await this.commercetools.login(
54
- payload.username,
55
- payload.password
63
+ public override async login(payload: IdentityMutationLogin): Promise<Result<IdentityFactoryOutput<TFactory>>> {
64
+ const identity = this.factory.parseIdentity(
65
+ this.context,
66
+ await this.commercetools.login(
67
+ payload.username,
68
+ payload.password
69
+ )
56
70
  );
57
71
 
58
72
  this.updateIdentityContext(identity);
@@ -63,8 +77,11 @@ export class CommercetoolsIdentityProvider extends IdentityProvider {
63
77
  @Reactionary({
64
78
  outputSchema: IdentitySchema,
65
79
  })
66
- public override async logout(payload: Record<string, never>): Promise<Result<Identity>> {
67
- const identity = await this.commercetools.logout();
80
+ public override async logout(payload: Record<string, never>): Promise<Result<IdentityFactoryOutput<TFactory>>> {
81
+ const identity = this.factory.parseIdentity(
82
+ this.context,
83
+ await this.commercetools.logout(),
84
+ );
68
85
 
69
86
  this.updateIdentityContext(identity);
70
87
 
@@ -77,10 +94,13 @@ export class CommercetoolsIdentityProvider extends IdentityProvider {
77
94
  })
78
95
  public override async register(
79
96
  payload: IdentityMutationRegister
80
- ): Promise<Result<Identity>> {
81
- const identity = await this.commercetools.register(
82
- payload.username,
83
- payload.password
97
+ ): Promise<Result<IdentityFactoryOutput<TFactory>>> {
98
+ const identity = this.factory.parseIdentity(
99
+ this.context,
100
+ await this.commercetools.register(
101
+ payload.username,
102
+ payload.password
103
+ )
84
104
  );
85
105
 
86
106
  this.updateIdentityContext(identity);