@mframework/layer-commerce 0.0.3

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 (355) hide show
  1. package/README.md +101 -0
  2. package/app/cart/useCart.ts +1 -0
  3. package/app/components/ChevronIcon/ChevronIcon.config.ts +17 -0
  4. package/app/components/DateSelect/DateSelect.config.ts +15 -0
  5. package/app/components/Field/Field.config.ts +14 -0
  6. package/app/components/FieldDate/FieldDate.config.ts +16 -0
  7. package/app/components/Form/Form.type.ts +8 -0
  8. package/app/components/Product/Product.config.ts +19 -0
  9. package/app/components/Product/Stock.config.ts +15 -0
  10. package/app/components/ProductCustomizableOption/ProductCustomizableOption.config.ts +5 -0
  11. package/app/components/ProductGallery/ProductGallery.config.ts +15 -0
  12. package/app/components/ProductReviews/ProductReviews.config.ts +8 -0
  13. package/app/composables/_types.ts +18 -0
  14. package/app/composables/adapters/abstract/cartAdapter.ts +0 -0
  15. package/app/composables/adapters/abstract/categoryAdapter.ts +0 -0
  16. package/app/composables/adapters/abstract/customerAdapter.ts +0 -0
  17. package/app/composables/adapters/abstract/inventoryAdapter.ts +0 -0
  18. package/app/composables/adapters/abstract/orderAdapter.ts +0 -0
  19. package/app/composables/adapters/abstract/productAdapter.ts +7 -0
  20. package/app/composables/cart/registry.ts +20 -0
  21. package/app/composables/cart/types.ts +18 -0
  22. package/app/composables/cart/useCart.ts +15 -0
  23. package/app/composables/config.ts +19 -0
  24. package/app/composables/defs/apiDefinitions.ts +55 -0
  25. package/app/composables/defs/extension.feature +40 -0
  26. package/app/composables/defs/extension.mocks.ts +39 -0
  27. package/app/composables/defs/extension.test.ts +280 -0
  28. package/app/composables/defs/extension.ts +236 -0
  29. package/app/composables/defs/index.ts +3 -0
  30. package/app/composables/defs/typeHelpers.ts +8 -0
  31. package/app/composables/defs/types.ts +136 -0
  32. package/app/composables/domain/product.ts +12 -0
  33. package/app/composables/featured-products.ts +20 -0
  34. package/app/composables/helpers/contextualizedNormalizers.feature +14 -0
  35. package/app/composables/helpers/contextualizedNormalizers.test.ts +85 -0
  36. package/app/composables/helpers/contextualizedNormalizers.ts +20 -0
  37. package/app/composables/helpers/index.ts +1 -0
  38. package/app/composables/index.ts +9 -0
  39. package/app/composables/methods/auth.ts +83 -0
  40. package/app/composables/methods/cart.ts +119 -0
  41. package/app/composables/methods/category.ts +27 -0
  42. package/app/composables/methods/checkout.ts +54 -0
  43. package/app/composables/methods/customer.ts +52 -0
  44. package/app/composables/methods/helpers.ts +5 -0
  45. package/app/composables/methods/index.ts +75 -0
  46. package/app/composables/methods/order.ts +39 -0
  47. package/app/composables/methods/product.ts +95 -0
  48. package/app/composables/methods/settings.ts +16 -0
  49. package/app/composables/models/cart.ts +95 -0
  50. package/app/composables/models/category.ts +13 -0
  51. package/app/composables/models/checkout.ts +17 -0
  52. package/app/composables/models/customer.ts +16 -0
  53. package/app/composables/models/facets.ts +25 -0
  54. package/app/composables/models/index.ts +94 -0
  55. package/app/composables/models/order.ts +43 -0
  56. package/app/composables/models/product.ts +73 -0
  57. package/app/composables/models/shared.ts +75 -0
  58. package/app/composables/orders.ts +69 -0
  59. package/app/composables/products/registry.ts +86 -0
  60. package/app/composables/products/types.ts +8 -0
  61. package/app/composables/products/useEvents.ts +26 -0
  62. package/app/composables/products/useGiftCards.ts +29 -0
  63. package/app/composables/products/useProducts.ts +12 -0
  64. package/app/composables/products/useSubscriptions.ts +29 -0
  65. package/app/composables/products.ts +30 -0
  66. package/app/composables/registry.ts +24 -0
  67. package/app/composables/useAuth.ts +43 -0
  68. package/app/composables/useBreakpoints/index.ts +1 -0
  69. package/app/composables/useBreakpoints/useBreakpoints.ts +28 -0
  70. package/app/composables/useCache.ts +38 -0
  71. package/app/composables/useCart/__tests__/useCart.spec.ts +11 -0
  72. package/app/composables/useCart/index.ts +1 -0
  73. package/app/composables/useCart/types.ts +17 -0
  74. package/app/composables/useCart/useCart.ts +46 -0
  75. package/app/composables/useCartShippingMethods/__tests__/useCartShippingMethods.spec.ts +11 -0
  76. package/app/composables/useCartShippingMethods/index.ts +1 -0
  77. package/app/composables/useCartShippingMethods/types.ts +17 -0
  78. package/app/composables/useCartShippingMethods/useCartShippingMethods.ts +47 -0
  79. package/app/composables/useCatalog.ts +26 -0
  80. package/app/composables/useContent.ts +26 -0
  81. package/app/composables/useCustomer/__tests__/useCustomer.spec.ts +25 -0
  82. package/app/composables/useCustomer/index.ts +2 -0
  83. package/app/composables/useCustomer/types.ts +17 -0
  84. package/app/composables/useCustomer/useCustomer.ts +40 -0
  85. package/app/composables/useCustomerAddress/__tests__/useCustomerAddress.spec.ts +11 -0
  86. package/app/composables/useCustomerAddress/index.ts +2 -0
  87. package/app/composables/useCustomerAddress/types.ts +17 -0
  88. package/app/composables/useCustomerAddress/useCustomerAddress.ts +55 -0
  89. package/app/composables/useCustomerOrder/__tests__/useCustomerOrder.spec.ts +11 -0
  90. package/app/composables/useCustomerOrder/adress.ts +10 -0
  91. package/app/composables/useCustomerOrder/index.ts +2 -0
  92. package/app/composables/useCustomerOrder/product.ts +37 -0
  93. package/app/composables/useCustomerOrder/types.ts +40 -0
  94. package/app/composables/useCustomerOrder/useCustomerOrder.ts +63 -0
  95. package/app/composables/useCustomerOrders/__tests__/useCustomerOrders.spec.ts +11 -0
  96. package/app/composables/useCustomerOrders/index.ts +2 -0
  97. package/app/composables/useCustomerOrders/types.ts +20 -0
  98. package/app/composables/useCustomerOrders/useCustomerOrders.ts +56 -0
  99. package/app/composables/useCustomerReturns/__tests__/useCustomerReturns.spec.ts +11 -0
  100. package/app/composables/useCustomerReturns/index.ts +2 -0
  101. package/app/composables/useCustomerReturns/types.ts +17 -0
  102. package/app/composables/useCustomerReturns/useCustomerReturns.ts +41 -0
  103. package/app/composables/useHandleError/index.ts +1 -0
  104. package/app/composables/useHandleError/types.ts +11 -0
  105. package/app/composables/useHandleError/useHandleError.ts +27 -0
  106. package/app/composables/useInventory.ts +29 -0
  107. package/app/composables/useLoading.ts +21 -0
  108. package/app/composables/useNotification.ts +21 -0
  109. package/app/composables/usePageTitle.ts +20 -0
  110. package/app/composables/useProduct/index.ts +2 -0
  111. package/app/composables/useProduct/types.ts +17 -0
  112. package/app/composables/useProduct/useProduct.ts +42 -0
  113. package/app/composables/useProductAttribute/__tests__/useProduct.mock.ts +31 -0
  114. package/app/composables/useProductAttribute/__tests__/useProductAttribute.spec.ts +14 -0
  115. package/app/composables/useProductAttribute/index.ts +1 -0
  116. package/app/composables/useProductAttribute/useProductAttribute.ts +37 -0
  117. package/app/composables/useProductRecommended/__tests__/useProductRecommended.spec.ts +12 -0
  118. package/app/composables/useProductRecommended/index.ts +1 -0
  119. package/app/composables/useProductRecommended/types.ts +17 -0
  120. package/app/composables/useProductRecommended/useProductRecommended.ts +43 -0
  121. package/app/composables/useProductReviews/__tests__/productReviews.mock.ts +20 -0
  122. package/app/composables/useProductReviews/__tests__/useProductReviews.spec.ts +22 -0
  123. package/app/composables/useProductReviews/index.ts +2 -0
  124. package/app/composables/useProductReviews/types.ts +17 -0
  125. package/app/composables/useProductReviews/useProductReviews.ts +46 -0
  126. package/app/composables/useProducts/__tests__/useProducts.spec.ts +11 -0
  127. package/app/composables/useProducts/types.ts +22 -0
  128. package/app/composables/useProducts/useProducts.ts +41 -0
  129. package/app/composables/useTax.ts +27 -0
  130. package/app/composables/validationRules/index.ts +1 -0
  131. package/app/composables/validationRules/password.feature +67 -0
  132. package/app/composables/validationRules/password.test.ts +89 -0
  133. package/app/composables/validationRules/password.ts +25 -0
  134. package/app/normalizers/Cart.query.ts +729 -0
  135. package/app/normalizers/Cart.type.ts +285 -0
  136. package/app/normalizers/Category.query.ts +146 -0
  137. package/app/normalizers/Category.type.ts +55 -0
  138. package/app/normalizers/CheckEmail.query.ts +28 -0
  139. package/app/normalizers/Checkout.query.ts +253 -0
  140. package/app/normalizers/Checkout.type.ts +77 -0
  141. package/app/normalizers/CmsBlock.query.ts +57 -0
  142. package/app/normalizers/CmsBlock.type.ts +25 -0
  143. package/app/normalizers/CmsPage.query.ts +59 -0
  144. package/app/normalizers/CmsPage.type.ts +26 -0
  145. package/app/normalizers/Config.query.ts +224 -0
  146. package/app/normalizers/Config.type.ts +196 -0
  147. package/app/normalizers/ContactForm.query.ts +49 -0
  148. package/app/normalizers/CreditMemo.type.ts +49 -0
  149. package/app/normalizers/GiftCard.type.ts +24 -0
  150. package/app/normalizers/Invoice.type.ts +58 -0
  151. package/app/normalizers/Menu.query.ts +54 -0
  152. package/app/normalizers/Menu.type.ts +22 -0
  153. package/app/normalizers/MyAccount.query.ts +268 -0
  154. package/app/normalizers/MyAccount.type.ts +129 -0
  155. package/app/normalizers/NewsletterSubscription.query.ts +38 -0
  156. package/app/normalizers/Order.query.ts +741 -0
  157. package/app/normalizers/Order.type.ts +268 -0
  158. package/app/normalizers/Payment.type.ts +28 -0
  159. package/app/normalizers/ProductAlerts.query.ts +23 -0
  160. package/app/normalizers/ProductCompare.query.ts +226 -0
  161. package/app/normalizers/ProductCompare.type.ts +90 -0
  162. package/app/normalizers/ProductList.query.ts +1620 -0
  163. package/app/normalizers/ProductList.type.ts +726 -0
  164. package/app/normalizers/Region.query.ts +58 -0
  165. package/app/normalizers/Region.type.ts +23 -0
  166. package/app/normalizers/Return.type.ts +50 -0
  167. package/app/normalizers/Review.query.ts +81 -0
  168. package/app/normalizers/Review.type.ts +42 -0
  169. package/app/normalizers/Slider.query.ts +72 -0
  170. package/app/normalizers/Slider.type.ts +26 -0
  171. package/app/normalizers/StoreInPickUp.query.ts +54 -0
  172. package/app/normalizers/StoreInPickUp.type.ts +59 -0
  173. package/app/normalizers/Subscription.type.ts +25 -0
  174. package/app/normalizers/Transaction.type.ts +20 -0
  175. package/app/normalizers/UrlRewrites.query.ts +55 -0
  176. package/app/normalizers/UrlRewrites.type.ts +25 -0
  177. package/app/normalizers/Wishlist.query.ts +202 -0
  178. package/app/normalizers/Wishlist.type.ts +42 -0
  179. package/app/pages/brand/[...slug].vue +76 -0
  180. package/app/pages/brands.vue +67 -0
  181. package/app/pages/cart.vue +142 -0
  182. package/app/pages/compare.vue +166 -0
  183. package/app/pages/departments/[...slug].vue +353 -0
  184. package/app/pages/departments/category/[...slug].vue +114 -0
  185. package/app/pages/incentive/[...id].vue +66 -0
  186. package/app/pages/invoice/[id].vue +309 -0
  187. package/app/pages/order/[id].vue +327 -0
  188. package/app/pages/product/[...id].vue +309 -0
  189. package/app/pages/product/showcases/index.vue +86 -0
  190. package/app/pages/shipment/[...id].vue +176 -0
  191. package/app/pages/shop/[...slug].vue +158 -0
  192. package/app/pages/shops.vue +76 -0
  193. package/app/pages/subscription/[...id].vue +147 -0
  194. package/app/pages/transaction/[...id].vue +74 -0
  195. package/app/routes/CategoryPage/CategoryPage.config.ts +28 -0
  196. package/app/routes/CategoryPage/CategoryPage.type.ts +8 -0
  197. package/app/routes/Checkout/Checkout.config.ts +3 -0
  198. package/app/routes/Checkout/Checkout.type.ts +14 -0
  199. package/app/routes/MyAccount/MyAccount.config.ts +1 -0
  200. package/app/routes/SearchPage/SearchPage.config.ts +1 -0
  201. package/app/routes/UrlRewrites/UrlRewrites.config.ts +5 -0
  202. package/app/stores/Cart/Cart.type.ts +26 -0
  203. package/app/stores/MyAccount/MyAccount.action.ts +7 -0
  204. package/app/stores/Notification/Notification.action.ts +40 -0
  205. package/app/stores/Notification/Notification.type.ts +16 -0
  206. package/app/stores/Popup/Popup.action.ts +30 -0
  207. package/app/stores/Product/Product.dispatcher.ts +53 -0
  208. package/app/stores/Product/Product.reducer.ts +12 -0
  209. package/app/stores/ProductList/ProductList.dispatcher.ts +35 -0
  210. package/app/stores/ProductList/ProductList.reducer.ts +13 -0
  211. package/app/stores/Store.type.ts +31 -0
  212. package/app/stores/Wishlist/Wishlist.type.ts +12 -0
  213. package/app/stores/cart.ts +218 -0
  214. package/app/stores/cartStore.ts +224 -0
  215. package/app/stores/checkout.ts +18 -0
  216. package/app/stores/compare.ts +65 -0
  217. package/app/stores/currency.js +29 -0
  218. package/app/stores/digital-products.js +11 -0
  219. package/app/stores/orders.ts +172 -0
  220. package/app/stores/product.ts +34 -0
  221. package/app/stores/productList.ts +35 -0
  222. package/app/stores/productListInfo.ts +0 -0
  223. package/app/stores/products.ts +118 -0
  224. package/app/stores/recentlyViewedProducts.ts +56 -0
  225. package/app/stores/review.ts +33 -0
  226. package/app/stores/storeInPickUp.ts +21 -0
  227. package/app/stores/user.ts +20 -0
  228. package/app/stores/wishlist.ts +46 -0
  229. package/app/types/Account.type.ts +141 -0
  230. package/app/types/Breadcrumbs.type.ts +23 -0
  231. package/app/types/CMS.type.ts +33 -0
  232. package/app/types/Category.type.ts +67 -0
  233. package/app/types/Checkout.type.ts +58 -0
  234. package/app/types/Common.type.ts +77 -0
  235. package/app/types/Config.type.ts +47 -0
  236. package/app/types/Device.type.ts +37 -0
  237. package/app/types/Direction.type.ts +23 -0
  238. package/app/types/Downloadable.type.ts +24 -0
  239. package/app/types/Error.type.ts +22 -0
  240. package/app/types/Field.type.ts +151 -0
  241. package/app/types/Global.type.ts +156 -0
  242. package/app/types/Graphql.type.ts +4497 -0
  243. package/app/types/Layout.type.ts +18 -0
  244. package/app/types/Menu.type.ts +39 -0
  245. package/app/types/MiniCart.type.ts +61 -0
  246. package/app/types/NotificationList.type.ts +34 -0
  247. package/app/types/Order.type.ts +174 -0
  248. package/app/types/Price.type.ts +72 -0
  249. package/app/types/ProductCompare.type.ts +24 -0
  250. package/app/types/ProductList.type.ts +351 -0
  251. package/app/types/Rating.type.ts +42 -0
  252. package/app/types/Router.type.ts +67 -0
  253. package/app/types/Slider.type.ts +25 -0
  254. package/app/types/StockStatus.type.ts +21 -0
  255. package/app/types/domain/index.ts +94 -0
  256. package/app/types/index.ts +33 -0
  257. package/app/types/shims.d.ts +52 -0
  258. package/app/types/tilework-opus.d.ts +48 -0
  259. package/app/utils/Address/Address.type.ts +28 -0
  260. package/app/utils/Address/index.ts +325 -0
  261. package/app/utils/Auth/IsSignedIn.ts +4 -0
  262. package/app/utils/Auth/Token.ts +9 -0
  263. package/app/utils/Base64/Base64.ts +16 -0
  264. package/app/utils/Base64/index.ts +12 -0
  265. package/app/utils/Browser/Browser.ts +29 -0
  266. package/app/utils/Browser/index.ts +12 -0
  267. package/app/utils/BrowserDatabase/BrowserDatabase.ts +70 -0
  268. package/app/utils/BrowserDatabase/index.ts +12 -0
  269. package/app/utils/CSS/CSS.ts +65 -0
  270. package/app/utils/CSS/index.ts +12 -0
  271. package/app/utils/Cache/Cache.ts +99 -0
  272. package/app/utils/Cart/Cart.ts +300 -0
  273. package/app/utils/Cart/Cart.type.ts +76 -0
  274. package/app/utils/Cart/Token.ts +59 -0
  275. package/app/utils/Cart/index.ts +13 -0
  276. package/app/utils/Category/Filters.ts +39 -0
  277. package/app/utils/Category/index.ts +12 -0
  278. package/app/utils/Common/index.ts +32 -0
  279. package/app/utils/Compare/Compare.ts +89 -0
  280. package/app/utils/Compare/index.ts +12 -0
  281. package/app/utils/Currency/Currency.ts +84 -0
  282. package/app/utils/Currency/index.ts +12 -0
  283. package/app/utils/DynamicReducer/DynamicReducer.type.ts +14 -0
  284. package/app/utils/DynamicReducer/Helper.ts +30 -0
  285. package/app/utils/DynamicReducer/index.tsx +35 -0
  286. package/app/utils/ElementTransition/ElementTransition.ts +100 -0
  287. package/app/utils/Form/Extract.ts +316 -0
  288. package/app/utils/Form/Form.ts +46 -0
  289. package/app/utils/Form/Form.type.ts +60 -0
  290. package/app/utils/Form/Transform.ts +33 -0
  291. package/app/utils/FormPortalCollector/index.ts +45 -0
  292. package/app/utils/History/History.type.ts +31 -0
  293. package/app/utils/History/index.ts +17 -0
  294. package/app/utils/Manipulations/Array.ts +18 -0
  295. package/app/utils/Manipulations/Date.ts +36 -0
  296. package/app/utils/Manipulations/index.ts +14 -0
  297. package/app/utils/Media/Media.ts +27 -0
  298. package/app/utils/Media/index.ts +13 -0
  299. package/app/utils/Menu/Menu.ts +116 -0
  300. package/app/utils/Menu/Menu.type.ts +37 -0
  301. package/app/utils/Menu/index.ts +12 -0
  302. package/app/utils/Mobile/index.ts +13 -0
  303. package/app/utils/Mobile/isMobile.ts +34 -0
  304. package/app/utils/Orders/Orders.ts +71 -0
  305. package/app/utils/Orders/Orders.type.ts +19 -0
  306. package/app/utils/Orders/index.ts +13 -0
  307. package/app/utils/Polyfill/index.ts +336 -0
  308. package/app/utils/Preload/CategoryPreload.ts +74 -0
  309. package/app/utils/Preload/ProductPreload.ts +28 -0
  310. package/app/utils/Preload/index.ts +75 -0
  311. package/app/utils/Price/Price.config.ts +189 -0
  312. package/app/utils/Price/Price.ts +63 -0
  313. package/app/utils/Price/index.ts +12 -0
  314. package/app/utils/Product/Extract.ts +652 -0
  315. package/app/utils/Product/Product.ts +575 -0
  316. package/app/utils/Product/Product.type.ts +260 -0
  317. package/app/utils/Product/Transform.ts +382 -0
  318. package/app/utils/Product/index.ts +12 -0
  319. package/app/utils/Promise/MakeCancelable.ts +44 -0
  320. package/app/utils/Promise/Promise.type.ts +15 -0
  321. package/app/utils/Promise/index.ts +13 -0
  322. package/app/utils/Query/Field.ts +71 -0
  323. package/app/utils/Query/Fragment.ts +22 -0
  324. package/app/utils/Query/PrepareDocument.ts +119 -0
  325. package/app/utils/Query/Query.type.ts +26 -0
  326. package/app/utils/Query/index.ts +15 -0
  327. package/app/utils/Request/Config.ts +21 -0
  328. package/app/utils/Request/DataContainer.ts +102 -0
  329. package/app/utils/Request/Debounce.ts +48 -0
  330. package/app/utils/Request/Error.ts +31 -0
  331. package/app/utils/Request/Hash.ts +88 -0
  332. package/app/utils/Request/LowPriorityLoad.ts +32 -0
  333. package/app/utils/Request/LowPriorityRender.ts +55 -0
  334. package/app/utils/Request/Mutation.ts +25 -0
  335. package/app/utils/Request/Query.ts +25 -0
  336. package/app/utils/Request/QueryDispatcher.ts +135 -0
  337. package/app/utils/Request/Request.ts +310 -0
  338. package/app/utils/Store/Store.type.ts +26 -0
  339. package/app/utils/Store/index.ts +71 -0
  340. package/app/utils/Url/Url.ts +297 -0
  341. package/app/utils/Url/index.ts +12 -0
  342. package/app/utils/Validator/Config.ts +96 -0
  343. package/app/utils/Validator/Validator.ts +268 -0
  344. package/app/utils/Validator/Validator.type.ts +47 -0
  345. package/app/utils/Validator/index.ts +12 -0
  346. package/app/utils/Wishlist/Wishlist.ts +65 -0
  347. package/app/utils/Wishlist/index.ts +12 -0
  348. package/app/utils/client.ts +280 -0
  349. package/app/utils/index.ts +53 -0
  350. package/app/utils/normalizer.ts +23 -0
  351. package/app/utils/normalizers/magento.ts +29 -0
  352. package/app/utils/normalizers/shopify.ts +29 -0
  353. package/nuxt.config.ts +11 -0
  354. package/package.json +43 -0
  355. package/tsconfig.json +45 -0
@@ -0,0 +1,260 @@
1
+ /**
2
+ * M Framework - Flexible backend agnostic framework.
3
+ *
4
+ * Copyright © Meeovi, LTD. All rights reserved.
5
+ * See LICENSE for license details.
6
+ *
7
+ * @license OSL-3.0 (Open Software License ("OSL") v. 3.0)
8
+ * @package mframework/mframework-theme
9
+ * @link https://github.com/meeovi/mframework
10
+ */
11
+
12
+ import { ImageType } from 'Component/ProductGallery/ProductGallery.config';
13
+ import {
14
+ AttributeWithValue,
15
+ AttributeWithValueOption,
16
+ BundleItem,
17
+ BundleOption,
18
+ ConfigurableProductOptions,
19
+ CustomizableFieldValue,
20
+ CustomizableFileValue,
21
+ CustomizableProductFragmentOptions,
22
+ CustomizableSelectionValue,
23
+ GroupedProductItem,
24
+ PriceRange, ProductItem,
25
+ ProductReview,
26
+ ProductStockItem,
27
+ RatingsBreakdown,
28
+ SwatchData,
29
+ } from '../../normalizers/ProductList.type';
30
+ import { Product as DomainProduct } from '../../types/domain';
31
+ import { WishlistProduct } from '../../stores/Wishlist/Wishlist.type';
32
+ import { Merge } from '../../types/Common.type';
33
+ import { GQLCurrencyEnum, GQLProductStockStatus } from '../../types/Graphql.type';
34
+ import { DateRangeAttribute, YearRangeAttribute } from '../../utils/Form/Form.type';
35
+
36
+ export enum QtyFields {
37
+ SALABLE_QTY = 'salable_qty',
38
+ MIN_SALE_QTY = 'min_sale_qty',
39
+ MAX_SALE_QTY = 'max_sale_qty',
40
+ }
41
+
42
+ export const DEFAULT_MIN_PRODUCTS = 1;
43
+
44
+ export const DEFAULT_MAX_PRODUCTS = 999;
45
+
46
+ export type IndexedConfigurableOption = Merge<
47
+ Merge<ConfigurableProductOptions, IndexedAttributeWithValue>,
48
+ {
49
+ attribute_values: string[];
50
+ }
51
+ >;
52
+
53
+ export type IndexedConfigurableOptions = Record<string, IndexedConfigurableOption>;
54
+
55
+ export type IndexedVariant = Merge<ProductItem | DomainProduct, {
56
+ attributes: Record<string, IndexedAttributeWithValue>;
57
+ }>;
58
+
59
+ export type CleanCustomizableProductFragmentOptions = Omit<
60
+ CustomizableProductFragmentOptions,
61
+ 'CustomizableAreaOption' | 'CustomizableCheckboxOption' | 'CustomizableDateOption' | 'CustomizableDropDownOption'
62
+ | 'CustomizableFieldOption' | 'CustomizableFileOption' | 'CustomizableMultipleOption' | 'CustomizableRadioOption'
63
+ | 'checkboxValues' | 'dropdownValues' | 'fieldValues' | 'areaValues' | 'fileValues'
64
+ >;
65
+
66
+ export type IndexedCustomOptionValue = CustomizableSelectionValue
67
+ | CustomizableFieldValue
68
+ | CustomizableFileValue;
69
+
70
+ export type IndexedCustomOption = Merge<
71
+ CleanCustomizableProductFragmentOptions,
72
+ {
73
+ value: IndexedCustomOptionValue[] | CleanCustomizableProductFragmentOptions;
74
+ }
75
+ >;
76
+
77
+ export interface ReviewSummary {
78
+ rating_summary: number;
79
+ review_count: number;
80
+ }
81
+
82
+ export type IndexedBaseProduct<T> = Merge<T, {
83
+ configurable_options?: IndexedConfigurableOptions;
84
+ variants?: IndexedVariant[];
85
+ options?: IndexedCustomOption[];
86
+ attributes?: Record<string, IndexedAttributeWithValue>;
87
+ reviews?: IndexedReview[];
88
+ review_summary?: ReviewSummary;
89
+ items?: IndexedBundleItem[] | GroupedProductItem[];
90
+ // !FIXME: This prop is alway undefined. Added for compatibility with the legacy code.
91
+ productOptionsData?: Record<string, string | string[]>;
92
+ }>;
93
+
94
+ export type IndexedProduct = IndexedBaseProduct<Partial<ProductItem | DomainProduct>> & {
95
+ parent?: IndexedBaseProduct<Partial<ProductItem>>;
96
+ };
97
+
98
+ export type IndexedWishlistProduct = IndexedBaseProduct<Partial<WishlistProduct>>;
99
+
100
+ export type IndexedBundleOption = Merge<BundleOption, {
101
+ regularOptionPrice: number;
102
+ regularOptionPriceExclTax: number;
103
+ finalOptionPrice: number;
104
+ finalOptionPriceExclTax: number;
105
+ }>;
106
+
107
+ export type IndexedBundleItem = Merge<BundleItem, {
108
+ options?: IndexedBundleOption[];
109
+ }>;
110
+
111
+ export type IndexedAttributeWithValue = Merge<AttributeWithValue, {
112
+ attribute_options: Record<string, IndexedAttributeWithValueOption>;
113
+ }>;
114
+
115
+ export type IndexedAttributeWithValueOption = Merge<AttributeWithValueOption, {
116
+ swatch_data: SwatchData | null;
117
+ }>;
118
+
119
+ export type IndexedReview = Merge<ProductReview, {
120
+ rating_votes: RatingVote[];
121
+ }>;
122
+
123
+ export interface BuyRequestBundleOptions {
124
+ bundle_option: Record<string, string | Record<string, string>>;
125
+ bundle_option_qty: Record<string, number>;
126
+ }
127
+
128
+ export interface BuyRequestCustomizableOptions {
129
+ options: Record<string, string | string[] | Record<string, string>>;
130
+ }
131
+
132
+ export interface BuyRequestDownloadableOptions {
133
+ links: string[];
134
+ }
135
+
136
+ export interface BuyRequestConfigurableOptions {
137
+ super_attribute: Record<string, string>;
138
+ }
139
+
140
+ export interface PriceLabels {
141
+ baseLabel?: string;
142
+ priceLabel: string;
143
+ }
144
+
145
+ export interface ProductTransformData {
146
+ sku: string;
147
+ quantity: number;
148
+ selected_options: string[];
149
+ entered_options: ProductOption[];
150
+ }
151
+
152
+ export interface FormattedMoney {
153
+ value: number;
154
+ currency: GQLCurrencyEnum;
155
+ valueFormatted: string;
156
+ }
157
+
158
+ export interface ProductExtractBasePrice {
159
+ finalPrice: FormattedMoney;
160
+ finalPriceExclTax: FormattedMoney;
161
+ originalPrice: FormattedMoney;
162
+ originalPriceExclTax: FormattedMoney;
163
+ discount: { percentOff: number };
164
+ }
165
+
166
+ export interface ProductExtractOriginalPrice {
167
+ minRegularPrice: FormattedMoney;
168
+ minFinalPrice: FormattedMoney;
169
+ minFinalPriceExclTax: FormattedMoney;
170
+ maxRegularPrice: FormattedMoney;
171
+ maxFinalPrice: FormattedMoney;
172
+ maxFinalPriceExclTax: FormattedMoney;
173
+ }
174
+
175
+ export interface ProductExtractPriceConfiguration {
176
+ containsOptions: boolean;
177
+ containsOptionsWithPrice: boolean;
178
+ containsRequiredOptions: boolean;
179
+ containsRequiredOptionsWithPrice: boolean;
180
+ }
181
+
182
+ export interface ProductExtractPrice {
183
+ price: ProductExtractBasePrice;
184
+ originalPrice: ProductExtractOriginalPrice;
185
+ configuration: ProductExtractPriceConfiguration;
186
+ }
187
+
188
+ export type ProductExtractImage = Record<ImageType, { url?: string } | undefined>;
189
+
190
+ export interface TransformedBundleOption {
191
+ id: string;
192
+ name: string;
193
+ value: string;
194
+ label?: string;
195
+ subLabel: string;
196
+ sort_order: number;
197
+ isAvailable: boolean;
198
+ isDefault: boolean;
199
+ }
200
+
201
+ export type RatingVote = RatingsBreakdown & { percent: number };
202
+
203
+ export interface NoneRadioOption {
204
+ title: string;
205
+ label: string;
206
+ uid: string;
207
+ price: number;
208
+ finalOptionPrice: number;
209
+ can_change_quantity: boolean;
210
+ priceInclTax: number;
211
+ is_default: boolean;
212
+ }
213
+
214
+ export interface TransformedCustomizableOptions {
215
+ id: string;
216
+ name: string;
217
+ value: string;
218
+ label?: string;
219
+ subLabel: string;
220
+ sort_order: number;
221
+ }
222
+
223
+ export type GetYearRangeAttributes<IsYear extends boolean = false> = IsYear extends true
224
+ ? YearRangeAttribute
225
+ : DateRangeAttribute;
226
+
227
+ export interface StockCheckProduct {
228
+ type_id: string;
229
+ stock_status: GQLProductStockStatus;
230
+ stock_item?: ProductStockItem;
231
+ items?: Partial<StockCheckProduct>[];
232
+ variants?: Partial<StockCheckProduct>[];
233
+ }
234
+
235
+ export type ProductQuantity = number | Record<number, number>;
236
+
237
+ export interface ProductOption {
238
+ uid: string;
239
+ value: string;
240
+ }
241
+
242
+ export interface AdjustedPrice {
243
+ exclTax: number;
244
+ inclTax: number;
245
+ requiresDiscountCalculations: boolean;
246
+ hasDiscountCalculated: boolean;
247
+ }
248
+
249
+ export interface AdjustedPriceMap {
250
+ downloadable: AdjustedPrice;
251
+ bundle: AdjustedPrice;
252
+ config: AdjustedPrice;
253
+ }
254
+
255
+ export interface ProductPrice {
256
+ minimum_price: Partial<PriceRange>;
257
+ maximum_price: Partial<PriceRange>;
258
+ }
259
+
260
+ export type ConfigurableProductSelectedVariantValue = string | number | boolean;
@@ -0,0 +1,382 @@
1
+ /* eslint-disable @typescript-eslint/default-param-last */
2
+ /**
3
+ * M Framework - Flexible backend agnostic framework.
4
+ *
5
+ * Copyright © Meeovi, LTD. All rights reserved.
6
+ * See LICENSE for license details.
7
+ *
8
+ * @license OSL-3.0 (Open Software License ("OSL") v. 3.0)
9
+ * @package mframework/mframework
10
+ * @link https://github.com/meeovi/mframework
11
+ */
12
+
13
+ import { FieldType } from 'Component/Field/Field.config';
14
+ import { ProductType } from 'Component/Product/Product.config';
15
+ import { NONE_RADIO_OPTION } from 'Component/ProductCustomizableOption/ProductCustomizableOption.config';
16
+ import { CustomizableSelectionValue, GroupedProductItem } from '../../normalizers/ProductList.type';
17
+ import { GQLCurrencyEnum } from '../../types/Graphql.type';
18
+ import { decodeBase64, encodeBase64 } from '../../utils/Base64';
19
+ import { formatPrice } from '../../utils/Price';
20
+ import { ProductOption } from '../../utils/Product/Product.type';
21
+
22
+ import { getProductInStock } from './Extract';
23
+ import { ADD_TO_CART } from './Product';
24
+ import {
25
+ BuyRequestBundleOptions,
26
+ BuyRequestCustomizableOptions,
27
+ BuyRequestDownloadableOptions,
28
+ IndexedAttributeWithValue,
29
+ IndexedBundleOption,
30
+ IndexedProduct,
31
+ NoneRadioOption,
32
+ PriceLabels,
33
+ ProductTransformData,
34
+ StockCheckProduct,
35
+ TransformedBundleOption,
36
+ TransformedCustomizableOptions,
37
+ } from './Product.type';
38
+
39
+ export const PRICE_TYPE_PERCENT = 'PERCENT';
40
+
41
+ /**
42
+ * Generates correct UID for bundle with changed quantity
43
+ * UID is encoded in base64, original value is bundle/option_id/item_id/quantity
44
+ *
45
+ * @param uid
46
+ * @param quantity
47
+ * @namespace ../../utils/Product/Transform/getEncodedBundleUid
48
+ */
49
+ export const getEncodedBundleUid = (uid: string, quantity: number): string => {
50
+ const decoded = decodeBase64(uid);
51
+ const parts = decoded.split('/');
52
+ // eslint-disable-next-line no-magic-numbers
53
+ const newUid = parts.length === 3
54
+ ? `bundle/${parts[1]}/${quantity}`
55
+ : `bundle/${parts[1]}/${parts[2]}/${quantity}`;
56
+
57
+ return encodeBase64(newUid);
58
+ };
59
+
60
+ /** @namespace ../../utils/Product/Transform/getBundleOptions */
61
+ export const getBundleOptions = (buyRequest: string): string[] => {
62
+ const { bundle_option = {}, bundle_option_qty = {} }: BuyRequestBundleOptions = JSON.parse(buyRequest);
63
+
64
+ if (!bundle_option) {
65
+ return [];
66
+ }
67
+
68
+ return Object.entries(bundle_option).reduce((prev: string[], [option, variant]) => {
69
+ const qty = bundle_option_qty[option] || 1;
70
+
71
+ if (Array.isArray(variant) && variant.every((val) => typeof (val) === 'string')) {
72
+ return [...prev, ...variant.map((val) => encodeBase64(`bundle/${option}/${val}/${qty}`))];
73
+ }
74
+
75
+ return [...prev, ...Object.keys(variant).map((id) => encodeBase64(`bundle/${option}/${id}/${qty}`))];
76
+ }, []);
77
+ };
78
+
79
+ /** @namespace ../../utils/Product/Transform/getCustomizableOptions */
80
+ export const getCustomizableOptions = (buyRequest: string): string[] => {
81
+ const { options = {} }: BuyRequestCustomizableOptions = JSON.parse(buyRequest);
82
+
83
+ // handle null
84
+ if (!options) {
85
+ return [];
86
+ }
87
+
88
+ return Object.entries(options).reduce<string[]>(
89
+ (prev, [option, variant]) => {
90
+ if (typeof variant === 'string') {
91
+ return [...prev, encodeBase64(`custom-option/${option}/${variant}`)];
92
+ }
93
+
94
+ if (Array.isArray(variant)) {
95
+ return [...prev, ...variant.map((id) => encodeBase64(`custom-option/${option}/${id}`))];
96
+ }
97
+
98
+ if (typeof variant === 'object' && (variant.date_internal || variant.date)) {
99
+ const { date_internal, date } = variant;
100
+
101
+ return [...prev, encodeBase64(`custom-option/${option}/${date_internal || date}`)];
102
+ }
103
+
104
+ // Handle case when we need to pass previously uploaded file as selected option
105
+ // Normally files are passed via entered_options, but when customer adds product with attachment from wishlist,
106
+ // we need to reference data of the already uploaded file
107
+ if (typeof variant === 'object' && variant.type === 'application/octet-stream') {
108
+ return [...prev, encodeBase64(`custom-option/${option}/file-${encodeBase64(JSON.stringify(variant))}`)];
109
+ }
110
+
111
+ return prev;
112
+ },
113
+ [],
114
+ );
115
+ };
116
+
117
+ /** @namespace ../../utils/Product/Transform/getDownloadableOptions */
118
+ export const getDownloadableOptions = (buyRequest: string): string[] => {
119
+ const { links }: BuyRequestDownloadableOptions = JSON.parse(buyRequest);
120
+
121
+ if (!links) {
122
+ return [];
123
+ }
124
+
125
+ return links.map((link) => encodeBase64(`downloadable/${link}`));
126
+ };
127
+
128
+ /** @namespace ../../utils/Product/Transform/getConfigurableOptions */
129
+ export const getConfigurableOptions = (buyRequest: string): string[] => {
130
+ const { super_attribute } = JSON.parse(buyRequest);
131
+
132
+ if (!super_attribute) {
133
+ return [];
134
+ }
135
+
136
+ return Object.entries(super_attribute).map(([attr, value]) => encodeBase64(`configurable/${attr}/${value}`));
137
+ };
138
+
139
+ /** @namespace ../../utils/Product/Transform/getSelectedOptions */
140
+ export const getSelectedOptions = (buyRequest: string): string[] => [
141
+ ...getBundleOptions(buyRequest),
142
+ ...getCustomizableOptions(buyRequest),
143
+ ...getDownloadableOptions(buyRequest),
144
+ ...getConfigurableOptions(buyRequest),
145
+ ];
146
+
147
+ /** @namespace ../../utils/Product/Transform/transformParameters */
148
+ export const transformParameters = (
149
+ parameters: Record<string, string>,
150
+ attributes: Record<string, IndexedAttributeWithValue>,
151
+ ): string[] => Object.entries(parameters)
152
+ .map(([attrCode, selectedValue]) => {
153
+ const attrId = attributes[attrCode]?.attribute_id;
154
+
155
+ return encodeBase64(`configurable/${attrId}/${selectedValue}`);
156
+ });
157
+
158
+ /**
159
+ * Generates label for bundle option
160
+ *
161
+ * @param option
162
+ * @param currencyCode
163
+ * @returns {{baseLabel: string, priceLabel: string}}
164
+ * @namespace ../../utils/Product/Transform/bundleOptionToLabel
165
+ */
166
+ export const bundleOptionToLabel = (
167
+ option: Partial<IndexedBundleOption>,
168
+ currencyCode = GQLCurrencyEnum.USD,
169
+ ): PriceLabels => {
170
+ const {
171
+ price,
172
+ finalOptionPrice = 0,
173
+ price_type: priceType,
174
+ can_change_quantity: canChangeQuantity,
175
+ quantity = 0,
176
+ label,
177
+ product,
178
+ } = option || {};
179
+
180
+ const noPrice = price === 0 && finalOptionPrice === 0;
181
+ const priceLabel = noPrice ? '' : `+ ${ formatPrice(finalOptionPrice, currencyCode) }`;
182
+ const percentLabel = (noPrice || priceType !== PRICE_TYPE_PERCENT) ? '' : `(${ price }%)`;
183
+ // Accessing name here, because product may be passed as null - which prevents from assigning its
184
+ // default value, thus resulting in error
185
+ const fallbackLabel = product ? product.name : __('Option');
186
+ const renderLabel = label ?? fallbackLabel;
187
+
188
+ return {
189
+ baseLabel: !canChangeQuantity && quantity > 0 ? `${ quantity } x ${ renderLabel } ` : `${ renderLabel } `,
190
+ priceLabel: `${ priceLabel } ${ percentLabel }`,
191
+ };
192
+ };
193
+
194
+ /**
195
+ * Converts bundle products options into select field options,
196
+ * meaning into [uid:label] pair
197
+ *
198
+ * @param options
199
+ * @namespace ../../utils/Product/Transform/bundleOptionsToSelectTransform
200
+ */
201
+ export const bundleOptionsToSelectTransform = (
202
+ options: IndexedBundleOption[],
203
+ currencyCode = GQLCurrencyEnum.USD,
204
+ quantity: Record<string, number> = {},
205
+ ): TransformedBundleOption[] => (
206
+ options.reduce((result: TransformedBundleOption[] = [], option) => {
207
+ const {
208
+ uid: sourceUid = '',
209
+ quantity: defaultQuantity = 1,
210
+ position,
211
+ product,
212
+ is_default,
213
+ } = option;
214
+
215
+ const isAvailable = getProductInStock(product);
216
+
217
+ const {
218
+ priceLabel,
219
+ baseLabel,
220
+ } = bundleOptionToLabel(option, currencyCode);
221
+
222
+ const { [sourceUid]: currentQty = defaultQuantity } = quantity;
223
+ const uid = getEncodedBundleUid(sourceUid, currentQty);
224
+
225
+ result.push({
226
+ id: sourceUid,
227
+ name: sourceUid,
228
+ value: uid,
229
+ label: baseLabel,
230
+ subLabel: priceLabel,
231
+ sort_order: position,
232
+ isAvailable,
233
+ isDefault: is_default,
234
+ });
235
+
236
+ return result;
237
+ }, [])
238
+ );
239
+
240
+ /**
241
+ * Generates label for customizable option
242
+ *
243
+ * @param option
244
+ * @param currencyCode
245
+ * @returns {{baseLabel: string, priceLabel: string}}
246
+ * @namespace ../../utils/Product/Transform/customizableOptionToLabel
247
+ */
248
+ export const customizableOptionToLabel = (option: Partial<CustomizableSelectionValue>, currencyCode = GQLCurrencyEnum.USD): PriceLabels => {
249
+ const {
250
+ price,
251
+ priceInclTax = 0,
252
+ price_type,
253
+ title,
254
+ } = option || {};
255
+ const noPrice = price === 0 && priceInclTax === 0;
256
+ const priceLabel = noPrice ? '' : `+ ${ formatPrice(priceInclTax, currencyCode) }`;
257
+ const percentLabel = (noPrice || price_type !== PRICE_TYPE_PERCENT) ? '' : ` (${ price }%)`;
258
+
259
+ return {
260
+ baseLabel: title,
261
+ priceLabel: `${ priceLabel } ${ percentLabel }`,
262
+ };
263
+ };
264
+
265
+ /**
266
+ * Converts customizable products options into select field options,
267
+ * meaning into [uid:label] pair
268
+ *
269
+ * @param options
270
+ * @namespace ../../utils/Product/Transform/customizableOptionsToSelectTransform
271
+ */
272
+ export const customizableOptionsToSelectTransform = (
273
+ options: CustomizableSelectionValue[],
274
+ currencyCode = GQLCurrencyEnum.USD,
275
+ ): TransformedCustomizableOptions[] => (
276
+ options.reduce((result: TransformedCustomizableOptions[] = [], option) => {
277
+ const {
278
+ uid,
279
+ title,
280
+ sort_order = 0,
281
+ } = option;
282
+
283
+ const {
284
+ priceLabel,
285
+ baseLabel,
286
+ } = customizableOptionToLabel(option, currencyCode);
287
+
288
+ result.push({
289
+ id: uid,
290
+ name: title,
291
+ value: uid,
292
+ label: baseLabel,
293
+ subLabel: priceLabel,
294
+ sort_order,
295
+ });
296
+
297
+ return result;
298
+ }, [])
299
+ );
300
+
301
+ /**
302
+ * Generates Magento type product interface for performing
303
+ * actions (add to cart, wishlist, exc.)
304
+ * @param product
305
+ * @param quantity
306
+ * @param enteredOptions
307
+ * @param selectedOptions
308
+ * @returns {*[]}
309
+ * @namespace ../../utils/Product/Transform/magentoProductTransform
310
+ */
311
+ export const magentoProductTransform = (
312
+ action: string = ADD_TO_CART,
313
+ product: IndexedProduct,
314
+ quantity: number | Record<string, number> = 1,
315
+ enteredOptions: ProductOption[] = [],
316
+ selectedOptions: string[] = [],
317
+ ): ProductTransformData[] => {
318
+ const { sku = '', type_id: typeId } = product;
319
+
320
+ const productData: ProductTransformData[] = [];
321
+
322
+ if (typeId === ProductType.GROUPED && action === ADD_TO_CART) {
323
+ const { items = [] } = product;
324
+ const groupedProducts: string[] = [];
325
+
326
+ (items as GroupedProductItem[]).forEach(({ product: { id } }) => {
327
+ const { [String(id)]: groupedQuantity = 0 } = quantity as Record<string, number>;
328
+
329
+ groupedProducts.push(encodeBase64(`grouped/${id}/${groupedQuantity}`));
330
+ });
331
+
332
+ productData.push({
333
+ sku,
334
+ quantity: 1,
335
+ selected_options: [...selectedOptions, ...groupedProducts],
336
+ entered_options: enteredOptions,
337
+ });
338
+ } else {
339
+ const baseProductToAdd: ProductTransformData = {
340
+ sku,
341
+ quantity: quantity as number,
342
+ selected_options: selectedOptions,
343
+ entered_options: enteredOptions,
344
+ };
345
+
346
+ productData.push(baseProductToAdd);
347
+ }
348
+
349
+ return productData;
350
+ };
351
+
352
+ /**
353
+ *
354
+ * @param options
355
+ * @param isRequired
356
+ * @param type
357
+ * @returns {[{uid: string, price: number, priceInclTax: number, title: *, is_default: boolean},...*]|*}
358
+ * @namespace ../../utils/Product/Transform/nonRequiredRadioOptions
359
+ */
360
+ export const nonRequiredRadioOptions = <T>(
361
+ options: T | T[],
362
+ isRequired = false,
363
+ type: string = FieldType.RADIO,
364
+ ): T | Array<T | NoneRadioOption> => {
365
+ if (isRequired || type !== FieldType.RADIO) {
366
+ return options;
367
+ }
368
+
369
+ const hasDefault = (options as unknown as Array<
370
+ { is_default?: boolean; product: StockCheckProduct }
371
+ >).find(({ is_default, product }) => is_default && getProductInStock(product));
372
+
373
+ return [
374
+ {
375
+ ...(NONE_RADIO_OPTION as any),
376
+ is_default: !hasDefault,
377
+ },
378
+ ...(options as T[]),
379
+ ];
380
+ };
381
+
382
+ export default bundleOptionsToSelectTransform;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * M Framework - Flexible backend agnostic framework.
3
+ *
4
+ * Copyright © Meeovi, LTD. All rights reserved.
5
+ * See LICENSE for license details.
6
+ *
7
+ * @license OSL-3.0 (Open Software License ("OSL") v. 3.0)
8
+ * @package mframework/mframework
9
+ * @link https://github.com/meeovi/mframework
10
+ */
11
+
12
+ export * from './Product';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * M Framework - Flexible backend agnostic framework.
3
+ *
4
+ * Copyright © Meeovi, LTD. All rights reserved.
5
+ * See LICENSE for license details.
6
+ *
7
+ * @license OSL-3.0 (Open Software License ("OSL") v. 3.0)
8
+ * @package mframework/mframework
9
+ * @link https://github.com/meeovi/mframework
10
+ */
11
+
12
+ import { CancelablePromise } from './Promise.type';
13
+
14
+ /* eslint-disable prefer-promise-reject-errors */
15
+ // Disabled due promise being reject with custom error (isCanceled)
16
+
17
+ /**
18
+ * Promise wrapper to make it cancelable
19
+ * @static
20
+ * @param {Promise} promise promise which has to be cancelable
21
+ * @return {Promise} Cancelable promise
22
+ * @namespace ../../utils/Promise/MakeCancelable/makeCancelable */
23
+ export const makeCancelable = <T>(promise: Promise<T>): CancelablePromise<T> => {
24
+ // eslint-disable-next-line fp/no-let
25
+ let hasCanceled = false;
26
+
27
+ const wrappedPromise: Promise<T> = new Promise((resolve, reject) => {
28
+ promise.then(
29
+ /** @namespace ../../utils/Promise/MakeCancelable/makeCancelable/wrappedPromise/promise/then */
30
+ (val) => (!hasCanceled && resolve(val)),
31
+ /** @namespace ../../utils/Promise/MakeCancelable/makeCancelable/wrappedPromise/promise/then/catch */
32
+ (error) => (!hasCanceled && reject(error)),
33
+ );
34
+ });
35
+
36
+ return {
37
+ promise: wrappedPromise,
38
+ cancel() {
39
+ hasCanceled = true;
40
+ },
41
+ };
42
+ };
43
+
44
+ export default makeCancelable;