@lana-commerce/core 11.0.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.
- package/CHANGELOG.md +531 -0
- package/cjs/actionLock.js +31 -0
- package/cjs/addEmptyListItem.js +7 -0
- package/cjs/aggregateOptions.js +178 -0
- package/cjs/analytics.js +90 -0
- package/cjs/analyticsProductData.js +33 -0
- package/cjs/arrayToDict.js +12 -0
- package/cjs/asyncModuleWrapper.js +52 -0
- package/cjs/averageReviewScore.js +45 -0
- package/cjs/buildconfig.js +16 -0
- package/cjs/cachedLoader.js +36 -0
- package/cjs/canonicalVariantURL.js +2 -0
- package/cjs/cartOperation.js +132 -0
- package/cjs/categorySEO.js +20 -0
- package/cjs/commonTypes.js +2 -0
- package/cjs/compact.js +8 -0
- package/cjs/configLoader.js +69 -0
- package/cjs/controlledQueue.js +46 -0
- package/cjs/convertImageURL.js +19 -0
- package/cjs/dataLoader.js +185 -0
- package/cjs/defaultVariant.js +30 -0
- package/cjs/effector/clearOnChangeAfterDelay.js +17 -0
- package/cjs/effector/combineEvery.js +8 -0
- package/cjs/effector/combineSome.js +8 -0
- package/cjs/effector/debounced.js +18 -0
- package/cjs/effector/form.js +168 -0
- package/cjs/effector/hideOnChangeAfterDelay.js +17 -0
- package/cjs/effector/requestResponse.js +30 -0
- package/cjs/effector/requestResponseMulti.js +51 -0
- package/cjs/effector/restoreNamed.js +8 -0
- package/cjs/effector/split.js +29 -0
- package/cjs/effector/validator.js +33 -0
- package/cjs/effector/wrapSignInRequired.js +13 -0
- package/cjs/exceptions.js +6 -0
- package/cjs/fetchAllItems.js +56 -0
- package/cjs/file.js +83 -0
- package/cjs/fileWebsocket.js +83 -0
- package/cjs/filterFunc.js +48 -0
- package/cjs/filterFuncBrand.js +12 -0
- package/cjs/filterFuncCategory.js +12 -0
- package/cjs/filterFuncContentBlock.js +19 -0
- package/cjs/filterFuncCustomer.js +161 -0
- package/cjs/filterFuncDataFeed.js +54 -0
- package/cjs/filterFuncOrder.js +334 -0
- package/cjs/filterFuncPreprocess.js +14 -0
- package/cjs/filterFuncProduct.js +70 -0
- package/cjs/filterFuncPurchaseOrder.js +126 -0
- package/cjs/filterFuncSupplier.js +36 -0
- package/cjs/filterFuncTransfer.js +135 -0
- package/cjs/formatAbbrevNumber.js +21 -0
- package/cjs/formatCurrency.js +47 -0
- package/cjs/formatToJSX.js +123 -0
- package/cjs/fulfillmentNumber.js +7 -0
- package/cjs/generateRandomToken.js +12 -0
- package/cjs/generateUUID.js +10 -0
- package/cjs/generated/codes.js +47 -0
- package/cjs/genericFile.js +73 -0
- package/cjs/getSalesChannelID.js +13 -0
- package/cjs/getSessionID.js +13 -0
- package/cjs/getTimezone.js +12 -0
- package/cjs/graphql/fragments/Branding.js +3 -0
- package/cjs/graphql/fragments/BrandingField.js +3 -0
- package/cjs/graphql/fragments/CartCustomItem.js +3 -0
- package/cjs/graphql/fragments/CartOrder.js +3 -0
- package/cjs/graphql/fragments/CartVariant.js +3 -0
- package/cjs/graphql/fragments/CartVariantFull.js +3 -0
- package/cjs/graphql/fragments/Category.js +3 -0
- package/cjs/graphql/fragments/CommonCartVariant.js +3 -0
- package/cjs/graphql/fragments/Currency.js +3 -0
- package/cjs/graphql/fragments/CurrencyPrice.js +3 -0
- package/cjs/graphql/fragments/CustomField.js +3 -0
- package/cjs/graphql/fragments/CustomFieldObjects.js +3 -0
- package/cjs/graphql/fragments/Customer.js +3 -0
- package/cjs/graphql/fragments/CustomerBalance.js +3 -0
- package/cjs/graphql/fragments/CustomerBalanceHistory.js +3 -0
- package/cjs/graphql/fragments/CustomerFavorite.js +3 -0
- package/cjs/graphql/fragments/CustomerFavoriteShort.js +3 -0
- package/cjs/graphql/fragments/CustomerOAuthProvider.js +3 -0
- package/cjs/graphql/fragments/CustomerOrderBrief.js +3 -0
- package/cjs/graphql/fragments/CustomerOrderFulfillment.js +3 -0
- package/cjs/graphql/fragments/CustomerOrderFull.js +3 -0
- package/cjs/graphql/fragments/CustomerPaymentSource.js +3 -0
- package/cjs/graphql/fragments/CustomerReturnBrief.js +3 -0
- package/cjs/graphql/fragments/CustomerReturnFull.js +3 -0
- package/cjs/graphql/fragments/CustomerReturnPolicy.js +3 -0
- package/cjs/graphql/fragments/CustomerSubscriptionBrief.js +3 -0
- package/cjs/graphql/fragments/CustomerSubscriptionFull.js +3 -0
- package/cjs/graphql/fragments/File.js +3 -0
- package/cjs/graphql/fragments/FileForUpload.js +3 -0
- package/cjs/graphql/fragments/FileNoFallback.js +3 -0
- package/cjs/graphql/fragments/FullAddress.js +3 -0
- package/cjs/graphql/fragments/Gateway.js +3 -0
- package/cjs/graphql/fragments/GatewayManual.js +3 -0
- package/cjs/graphql/fragments/GatewayPaypal.js +3 -0
- package/cjs/graphql/fragments/GatewayStripe.js +3 -0
- package/cjs/graphql/fragments/GatewayTest.js +3 -0
- package/cjs/graphql/fragments/IPAndUAInfo.js +3 -0
- package/cjs/graphql/fragments/InfoCountry.js +3 -0
- package/cjs/graphql/fragments/InfoCountryDedupField.js +3 -0
- package/cjs/graphql/fragments/InfoCurrency.js +3 -0
- package/cjs/graphql/fragments/InfoProvince.js +3 -0
- package/cjs/graphql/fragments/KeyValue.js +3 -0
- package/cjs/graphql/fragments/LineItemField.js +3 -0
- package/cjs/graphql/fragments/MediaFile.js +3 -0
- package/cjs/graphql/fragments/MinCurrencyPrice.js +3 -0
- package/cjs/graphql/fragments/ProductField.js +3 -0
- package/cjs/graphql/fragments/ProductFieldSet.js +3 -0
- package/cjs/graphql/fragments/ProductFlat.js +3 -0
- package/cjs/graphql/fragments/ProductQuestion.js +3 -0
- package/cjs/graphql/fragments/ProductQuestionAnswer.js +3 -0
- package/cjs/graphql/fragments/ProductQuestionPage.js +3 -0
- package/cjs/graphql/fragments/ProductReview.js +3 -0
- package/cjs/graphql/fragments/ProductReviewAnswer.js +3 -0
- package/cjs/graphql/fragments/ProductReviewAverageScore.js +3 -0
- package/cjs/graphql/fragments/ProductReviewPage.js +3 -0
- package/cjs/graphql/fragments/ProductReviewScore.js +3 -0
- package/cjs/graphql/fragments/ProductReviewSurveyAnswer.js +3 -0
- package/cjs/graphql/fragments/ProductSearchOptionAgg.js +3 -0
- package/cjs/graphql/fragments/ProductSearchResult.js +3 -0
- package/cjs/graphql/fragments/ReturnReason.js +3 -0
- package/cjs/graphql/fragments/ReviewDimension.js +3 -0
- package/cjs/graphql/fragments/ReviewDimensionSet.js +3 -0
- package/cjs/graphql/fragments/ReviewImagePage.js +3 -0
- package/cjs/graphql/fragments/ReviewQuestionProduct.js +3 -0
- package/cjs/graphql/fragments/ReviewSettings.js +3 -0
- package/cjs/graphql/fragments/SearchProduct.js +3 -0
- package/cjs/graphql/fragments/Shop.js +3 -0
- package/cjs/graphql/fragments/SubscriptionPlan.js +3 -0
- package/cjs/graphql/fragments/SurveyQuestion.js +3 -0
- package/cjs/graphql/fragments/TieredPricing.js +3 -0
- package/cjs/graphql/fragments/TieredPricingTier.js +3 -0
- package/cjs/graphql/fragments/VariantOption.js +3 -0
- package/cjs/graphql/operations/ApplyGiftCardMutation.js +3 -0
- package/cjs/graphql/operations/AuthRequestMutation.js +3 -0
- package/cjs/graphql/operations/CancelOrderMutation.js +3 -0
- package/cjs/graphql/operations/CancelSubscriptionMutation.js +3 -0
- package/cjs/graphql/operations/ConnectOAuth2Mutation.js +3 -0
- package/cjs/graphql/operations/CreateCartMutation.js +26 -0
- package/cjs/graphql/operations/CreateFavoriteMutation.js +22 -0
- package/cjs/graphql/operations/CreateFileMutation.js +6 -0
- package/cjs/graphql/operations/CreatePaymentSourceMutation.js +6 -0
- package/cjs/graphql/operations/CreateProductQuestionAnswerMutation.js +3 -0
- package/cjs/graphql/operations/CreateProductQuestionMutation.js +8 -0
- package/cjs/graphql/operations/CreateProductReviewMutation.js +18 -0
- package/cjs/graphql/operations/CreateReturnMutation.js +22 -0
- package/cjs/graphql/operations/DeleteFavoriteMutation.js +3 -0
- package/cjs/graphql/operations/DeletePaymentSourceMutation.js +3 -0
- package/cjs/graphql/operations/DeleteProductQuestionAnswerMutation.js +3 -0
- package/cjs/graphql/operations/DeleteProductQuestionMutation.js +3 -0
- package/cjs/graphql/operations/DeleteProductReviewMutation.js +3 -0
- package/cjs/graphql/operations/DisconnectOAuth2Mutation.js +3 -0
- package/cjs/graphql/operations/EditSubscriptionMutation.js +3 -0
- package/cjs/graphql/operations/FileUploadedMutation.js +6 -0
- package/cjs/graphql/operations/FlagQuestionAnswerMutation.js +3 -0
- package/cjs/graphql/operations/FlagQuestionMutation.js +3 -0
- package/cjs/graphql/operations/FlagReviewAnswerMutation.js +3 -0
- package/cjs/graphql/operations/FlagReviewMutation.js +3 -0
- package/cjs/graphql/operations/GetBrandingQuery.js +10 -0
- package/cjs/graphql/operations/GetCartQuery.js +26 -0
- package/cjs/graphql/operations/GetCustomerAddressesPageDataQuery.js +16 -0
- package/cjs/graphql/operations/GetCustomerBalanceHistoryPageQuery.js +6 -0
- package/cjs/graphql/operations/GetCustomerBalanceQuery.js +8 -0
- package/cjs/graphql/operations/GetCustomerInfoQuery.js +10 -0
- package/cjs/graphql/operations/GetCustomerQuery.js +8 -0
- package/cjs/graphql/operations/GetFavoritesQuery.js +22 -0
- package/cjs/graphql/operations/GetFileStatusQuery.js +6 -0
- package/cjs/graphql/operations/GetGatewaysQuery.js +14 -0
- package/cjs/graphql/operations/GetInfoCurrenciesQuery.js +6 -0
- package/cjs/graphql/operations/GetLastCartQuery.js +26 -0
- package/cjs/graphql/operations/GetOrderQuery.js +30 -0
- package/cjs/graphql/operations/GetOrdersPageQuery.js +24 -0
- package/cjs/graphql/operations/GetPaymentMethodsPageDataQuery.js +18 -0
- package/cjs/graphql/operations/GetProductQuestionsPageQuery.js +10 -0
- package/cjs/graphql/operations/GetProductReviewImagesPageQuery.js +8 -0
- package/cjs/graphql/operations/GetProductReviewsPageQuery.js +20 -0
- package/cjs/graphql/operations/GetProvincesQuery.js +6 -0
- package/cjs/graphql/operations/GetQuestionQuery.js +8 -0
- package/cjs/graphql/operations/GetReturnCreationInfoQuery.js +36 -0
- package/cjs/graphql/operations/GetReturnQuery.js +28 -0
- package/cjs/graphql/operations/GetReturnsPageQuery.js +22 -0
- package/cjs/graphql/operations/GetReviewDimensionsQuery.js +6 -0
- package/cjs/graphql/operations/GetReviewQuery.js +18 -0
- package/cjs/graphql/operations/GetReviewSettingsQuery.js +12 -0
- package/cjs/graphql/operations/GetShopCurrenciesQuery.js +6 -0
- package/cjs/graphql/operations/GetShopQuery.js +8 -0
- package/cjs/graphql/operations/GetSubscriptionQuery.js +36 -0
- package/cjs/graphql/operations/GetSubscriptionsPageQuery.js +22 -0
- package/cjs/graphql/operations/GetVariantPageQuery.js +20 -0
- package/cjs/graphql/operations/LoadProductNoCustomerQuery.js +62 -0
- package/cjs/graphql/operations/LoadProductQuery.js +66 -0
- package/cjs/graphql/operations/ModifyCartMutation.js +26 -0
- package/cjs/graphql/operations/ModifyCustomerMutation.js +8 -0
- package/cjs/graphql/operations/ModifyFavoriteMutation.js +22 -0
- package/cjs/graphql/operations/ModifyProductQuestionAnswerMutation.js +3 -0
- package/cjs/graphql/operations/ModifyProductQuestionMutation.js +8 -0
- package/cjs/graphql/operations/ModifyProductReviewMutation.js +18 -0
- package/cjs/graphql/operations/NewPasswordMutation.js +3 -0
- package/cjs/graphql/operations/PauseSubscriptionMutation.js +3 -0
- package/cjs/graphql/operations/ResetPasswordMutation.js +3 -0
- package/cjs/graphql/operations/ResumeSubscriptionMutation.js +3 -0
- package/cjs/graphql/operations/SearchProductsAdvancedQuery.js +24 -0
- package/cjs/graphql/operations/SearchProductsQuery.js +20 -0
- package/cjs/graphql/operations/SearchQuestionsQuery.js +8 -0
- package/cjs/graphql/operations/SearchReviewsQuery.js +18 -0
- package/cjs/graphql/operations/SignInMutation.js +3 -0
- package/cjs/graphql/operations/SignInViaEmailCompleteMutation.js +3 -0
- package/cjs/graphql/operations/SignInViaEmailInitMutation.js +3 -0
- package/cjs/graphql/operations/SignUpMutation.js +3 -0
- package/cjs/graphql/operations/SkipNextSubscriptionMutation.js +3 -0
- package/cjs/graphql/operations/UploadFileMutation.js +3 -0
- package/cjs/graphql/operations/VerifyCodeMutation.js +3 -0
- package/cjs/graphql/operations/VoteQuestionAnswerMutation.js +3 -0
- package/cjs/graphql/operations/VoteQuestionMutation.js +3 -0
- package/cjs/graphql/operations/VoteReviewAnswerMutation.js +3 -0
- package/cjs/graphql/operations/VoteReviewMutation.js +3 -0
- package/cjs/graphql/types.js +2 -0
- package/cjs/hierarchicalSearchOption.js +42 -0
- package/cjs/idgen.js +8 -0
- package/cjs/ignoreQueue.js +50 -0
- package/cjs/imageAltProps.js +13 -0
- package/cjs/invoiceFormat.js +59 -0
- package/cjs/isShippingRequired.js +20 -0
- package/cjs/isoStripTrailingZeros.js +7 -0
- package/cjs/json/commerce.js +10 -0
- package/cjs/json/commerceFileUpload.js +57 -0
- package/cjs/json/commerceTypes.js +2 -0
- package/cjs/json/common.js +320 -0
- package/cjs/json/fetchAllItems.js +61 -0
- package/cjs/json/mutator.js +957 -0
- package/cjs/json/storefront.js +10 -0
- package/cjs/json/storefrontTypes.js +2 -0
- package/cjs/lastValue.js +17 -0
- package/cjs/lineItemPrice.js +111 -0
- package/cjs/loadJWT.js +25 -0
- package/cjs/mapInvalidInput.js +33 -0
- package/cjs/mapResponseData.js +16 -0
- package/cjs/mapResponseMultiData.js +14 -0
- package/cjs/meanBy.js +15 -0
- package/cjs/media.js +16 -0
- package/cjs/modules/advancedSearch.js +127 -0
- package/cjs/modules/cart.js +708 -0
- package/cjs/modules/config/defaultAdvancedSearchGraphQLConfig.js +8 -0
- package/cjs/modules/config/defaultCartGraphQLConfig.js +14 -0
- package/cjs/modules/config/defaultProductGraphQLConfig.js +48 -0
- package/cjs/modules/config/defaultSearchGraphQLConfig.js +8 -0
- package/cjs/modules/customer.js +2174 -0
- package/cjs/modules/helpers/cartInitOption.js +22 -0
- package/cjs/modules/helpers/cookieConsent.js +33 -0
- package/cjs/modules/helpers/customerOauth2.js +64 -0
- package/cjs/modules/helpers/getOAuth2Hook.js +52 -0
- package/cjs/modules/helpers/hookUpAnalytics.js +49 -0
- package/cjs/modules/helpers/loadJWT.js +23 -0
- package/cjs/modules/helpers/misc.js +58 -0
- package/cjs/modules/imageDialog.js +78 -0
- package/cjs/modules/persist.js +55 -0
- package/cjs/modules/popupMessage.js +21 -0
- package/cjs/modules/product.js +1261 -0
- package/cjs/modules/recentlyVisitedProducts.js +72 -0
- package/cjs/modules/search.js +102 -0
- package/cjs/multiResponseToResponse.js +22 -0
- package/cjs/nonNull.js +10 -0
- package/cjs/oauthState.js +40 -0
- package/cjs/orderShippingAddress.js +7 -0
- package/cjs/package.json +3 -0
- package/cjs/pender.js +16 -0
- package/cjs/percentageOff.js +7 -0
- package/cjs/popupConnectQueue.js +62 -0
- package/cjs/preact/components/SixDigitInput.js +167 -0
- package/cjs/preact/effector.js +74 -0
- package/cjs/preact/transition/CSSTransition.js +55 -0
- package/cjs/preact/transition/Transition.js +104 -0
- package/cjs/preact/translateLocalStatic.js +31 -0
- package/cjs/productFiltering.js +173 -0
- package/cjs/productSEO.js +51 -0
- package/cjs/productSorting.js +93 -0
- package/cjs/promiseAll.js +18 -0
- package/cjs/promiseLimit.js +38 -0
- package/cjs/rdsToInitialScores.js +32 -0
- package/cjs/react/components/Portal.js +7 -0
- package/cjs/react/components/RootCloseWrapper.js +41 -0
- package/cjs/react/components/SixDigitInput.js +167 -0
- package/cjs/react/contains.js +14 -0
- package/cjs/react/popperBinder.js +70 -0
- package/cjs/react/rootClose.js +112 -0
- package/cjs/react/translateLocalStatic.js +32 -0
- package/cjs/react/useAsyncCachedValue.js +14 -0
- package/cjs/refreshTimeout.js +25 -0
- package/cjs/remoteAuth.js +59 -0
- package/cjs/request.js +348 -0
- package/cjs/requestDetails.js +76 -0
- package/cjs/rfc3339Normalize.js +10 -0
- package/cjs/script.js +172 -0
- package/cjs/seo.js +2 -0
- package/cjs/shopDomain.js +8 -0
- package/cjs/shopLinks.js +63 -0
- package/cjs/slate.js +376 -0
- package/cjs/sleep.js +10 -0
- package/cjs/splitBy.js +21 -0
- package/cjs/splitName.js +28 -0
- package/cjs/stripZeros.js +13 -0
- package/cjs/stripeError.js +65 -0
- package/cjs/tailSplit.js +12 -0
- package/cjs/tieredPrice.js +32 -0
- package/cjs/timeIt.js +15 -0
- package/cjs/toMajor.js +8 -0
- package/cjs/toMinor.js +8 -0
- package/cjs/trace.js +37 -0
- package/cjs/translateLocale.js +12 -0
- package/cjs/traverse.js +14 -0
- package/cjs/truncate.js +21 -0
- package/cjs/typedLocalStorage.js +30 -0
- package/cjs/variantImage.js +26 -0
- package/cjs/variantImageURL.js +13 -0
- package/cjs/variantImages.js +19 -0
- package/cjs/variantInventory.js +43 -0
- package/cjs/variantOptions.js +21 -0
- package/cjs/variantPrice.js +96 -0
- package/cjs/variantPriceCommerce.js +29 -0
- package/cjs/variantTitle.js +9 -0
- package/cjs/variantTitleFull.js +11 -0
- package/cjs/variantURL.js +9 -0
- package/cjs/vendor/popper/index.d.ts +160 -0
- package/cjs/vendor/popper/index.js +2657 -0
- package/cjs/vendor/popper/index.js.map +1 -0
- package/cjs/vendor/popper/package.json +3 -0
- package/cjs/websocket.js +179 -0
- package/esm/actionLock.js +24 -0
- package/esm/addEmptyListItem.js +3 -0
- package/esm/aggregateOptions.js +169 -0
- package/esm/analytics.js +91 -0
- package/esm/analyticsProductData.js +28 -0
- package/esm/arrayToDict.js +8 -0
- package/esm/asyncModuleWrapper.js +47 -0
- package/esm/averageReviewScore.js +40 -0
- package/esm/buildconfig.js +13 -0
- package/esm/cachedLoader.js +32 -0
- package/esm/canonicalVariantURL.js +1 -0
- package/esm/cartOperation.js +126 -0
- package/esm/categorySEO.js +16 -0
- package/esm/commonTypes.js +1 -0
- package/esm/compact.js +4 -0
- package/esm/configLoader.js +61 -0
- package/esm/controlledQueue.js +38 -0
- package/esm/convertImageURL.js +15 -0
- package/esm/dataLoader.js +192 -0
- package/esm/defaultVariant.js +25 -0
- package/esm/effector/clearOnChangeAfterDelay.js +13 -0
- package/esm/effector/combineEvery.js +4 -0
- package/esm/effector/combineSome.js +4 -0
- package/esm/effector/debounced.js +14 -0
- package/esm/effector/form.js +166 -0
- package/esm/effector/hideOnChangeAfterDelay.js +13 -0
- package/esm/effector/requestResponse.js +24 -0
- package/esm/effector/requestResponseMulti.js +47 -0
- package/esm/effector/restoreNamed.js +4 -0
- package/esm/effector/split.js +25 -0
- package/esm/effector/validator.js +28 -0
- package/esm/effector/wrapSignInRequired.js +9 -0
- package/esm/exceptions.js +2 -0
- package/esm/fetchAllItems.js +44 -0
- package/esm/file.js +67 -0
- package/esm/fileWebsocket.js +75 -0
- package/esm/filterFunc.js +43 -0
- package/esm/filterFuncBrand.js +9 -0
- package/esm/filterFuncCategory.js +9 -0
- package/esm/filterFuncContentBlock.js +16 -0
- package/esm/filterFuncCustomer.js +153 -0
- package/esm/filterFuncDataFeed.js +50 -0
- package/esm/filterFuncOrder.js +325 -0
- package/esm/filterFuncPreprocess.js +9 -0
- package/esm/filterFuncProduct.js +66 -0
- package/esm/filterFuncPurchaseOrder.js +122 -0
- package/esm/filterFuncSupplier.js +31 -0
- package/esm/filterFuncTransfer.js +130 -0
- package/esm/formatAbbrevNumber.js +16 -0
- package/esm/formatCurrency.js +42 -0
- package/esm/formatToJSX.js +118 -0
- package/esm/fulfillmentNumber.js +3 -0
- package/esm/generateRandomToken.js +8 -0
- package/esm/generateUUID.js +6 -0
- package/esm/generated/codes.js +44 -0
- package/esm/genericFile.js +65 -0
- package/esm/getSalesChannelID.js +9 -0
- package/esm/getSessionID.js +9 -0
- package/esm/getTimezone.js +8 -0
- package/esm/graphql/fragments/Branding.js +1 -0
- package/esm/graphql/fragments/BrandingField.js +1 -0
- package/esm/graphql/fragments/CartCustomItem.js +1 -0
- package/esm/graphql/fragments/CartOrder.js +1 -0
- package/esm/graphql/fragments/CartVariant.js +1 -0
- package/esm/graphql/fragments/CartVariantFull.js +1 -0
- package/esm/graphql/fragments/Category.js +1 -0
- package/esm/graphql/fragments/CommonCartVariant.js +1 -0
- package/esm/graphql/fragments/Currency.js +1 -0
- package/esm/graphql/fragments/CurrencyPrice.js +1 -0
- package/esm/graphql/fragments/CustomField.js +1 -0
- package/esm/graphql/fragments/CustomFieldObjects.js +1 -0
- package/esm/graphql/fragments/Customer.js +1 -0
- package/esm/graphql/fragments/CustomerBalance.js +1 -0
- package/esm/graphql/fragments/CustomerBalanceHistory.js +1 -0
- package/esm/graphql/fragments/CustomerFavorite.js +1 -0
- package/esm/graphql/fragments/CustomerFavoriteShort.js +1 -0
- package/esm/graphql/fragments/CustomerOAuthProvider.js +1 -0
- package/esm/graphql/fragments/CustomerOrderBrief.js +1 -0
- package/esm/graphql/fragments/CustomerOrderFulfillment.js +1 -0
- package/esm/graphql/fragments/CustomerOrderFull.js +1 -0
- package/esm/graphql/fragments/CustomerPaymentSource.js +1 -0
- package/esm/graphql/fragments/CustomerReturnBrief.js +1 -0
- package/esm/graphql/fragments/CustomerReturnFull.js +1 -0
- package/esm/graphql/fragments/CustomerReturnPolicy.js +1 -0
- package/esm/graphql/fragments/CustomerSubscriptionBrief.js +1 -0
- package/esm/graphql/fragments/CustomerSubscriptionFull.js +1 -0
- package/esm/graphql/fragments/File.js +1 -0
- package/esm/graphql/fragments/FileForUpload.js +1 -0
- package/esm/graphql/fragments/FileNoFallback.js +1 -0
- package/esm/graphql/fragments/FullAddress.js +1 -0
- package/esm/graphql/fragments/Gateway.js +1 -0
- package/esm/graphql/fragments/GatewayManual.js +1 -0
- package/esm/graphql/fragments/GatewayPaypal.js +1 -0
- package/esm/graphql/fragments/GatewayStripe.js +1 -0
- package/esm/graphql/fragments/GatewayTest.js +1 -0
- package/esm/graphql/fragments/IPAndUAInfo.js +1 -0
- package/esm/graphql/fragments/InfoCountry.js +1 -0
- package/esm/graphql/fragments/InfoCountryDedupField.js +1 -0
- package/esm/graphql/fragments/InfoCurrency.js +1 -0
- package/esm/graphql/fragments/InfoProvince.js +1 -0
- package/esm/graphql/fragments/KeyValue.js +1 -0
- package/esm/graphql/fragments/LineItemField.js +1 -0
- package/esm/graphql/fragments/MediaFile.js +1 -0
- package/esm/graphql/fragments/MinCurrencyPrice.js +1 -0
- package/esm/graphql/fragments/ProductField.js +1 -0
- package/esm/graphql/fragments/ProductFieldSet.js +1 -0
- package/esm/graphql/fragments/ProductFlat.js +1 -0
- package/esm/graphql/fragments/ProductQuestion.js +1 -0
- package/esm/graphql/fragments/ProductQuestionAnswer.js +1 -0
- package/esm/graphql/fragments/ProductQuestionPage.js +1 -0
- package/esm/graphql/fragments/ProductReview.js +1 -0
- package/esm/graphql/fragments/ProductReviewAnswer.js +1 -0
- package/esm/graphql/fragments/ProductReviewAverageScore.js +1 -0
- package/esm/graphql/fragments/ProductReviewPage.js +1 -0
- package/esm/graphql/fragments/ProductReviewScore.js +1 -0
- package/esm/graphql/fragments/ProductReviewSurveyAnswer.js +1 -0
- package/esm/graphql/fragments/ProductSearchOptionAgg.js +1 -0
- package/esm/graphql/fragments/ProductSearchResult.js +1 -0
- package/esm/graphql/fragments/ReturnReason.js +1 -0
- package/esm/graphql/fragments/ReviewDimension.js +1 -0
- package/esm/graphql/fragments/ReviewDimensionSet.js +1 -0
- package/esm/graphql/fragments/ReviewImagePage.js +1 -0
- package/esm/graphql/fragments/ReviewQuestionProduct.js +1 -0
- package/esm/graphql/fragments/ReviewSettings.js +1 -0
- package/esm/graphql/fragments/SearchProduct.js +1 -0
- package/esm/graphql/fragments/Shop.js +1 -0
- package/esm/graphql/fragments/SubscriptionPlan.js +1 -0
- package/esm/graphql/fragments/SurveyQuestion.js +1 -0
- package/esm/graphql/fragments/TieredPricing.js +1 -0
- package/esm/graphql/fragments/TieredPricingTier.js +1 -0
- package/esm/graphql/fragments/VariantOption.js +1 -0
- package/esm/graphql/operations/ApplyGiftCardMutation.js +1 -0
- package/esm/graphql/operations/AuthRequestMutation.js +1 -0
- package/esm/graphql/operations/CancelOrderMutation.js +1 -0
- package/esm/graphql/operations/CancelSubscriptionMutation.js +1 -0
- package/esm/graphql/operations/ConnectOAuth2Mutation.js +1 -0
- package/esm/graphql/operations/CreateCartMutation.js +23 -0
- package/esm/graphql/operations/CreateFavoriteMutation.js +19 -0
- package/esm/graphql/operations/CreateFileMutation.js +3 -0
- package/esm/graphql/operations/CreatePaymentSourceMutation.js +3 -0
- package/esm/graphql/operations/CreateProductQuestionAnswerMutation.js +1 -0
- package/esm/graphql/operations/CreateProductQuestionMutation.js +5 -0
- package/esm/graphql/operations/CreateProductReviewMutation.js +15 -0
- package/esm/graphql/operations/CreateReturnMutation.js +19 -0
- package/esm/graphql/operations/DeleteFavoriteMutation.js +1 -0
- package/esm/graphql/operations/DeletePaymentSourceMutation.js +1 -0
- package/esm/graphql/operations/DeleteProductQuestionAnswerMutation.js +1 -0
- package/esm/graphql/operations/DeleteProductQuestionMutation.js +1 -0
- package/esm/graphql/operations/DeleteProductReviewMutation.js +1 -0
- package/esm/graphql/operations/DisconnectOAuth2Mutation.js +1 -0
- package/esm/graphql/operations/EditSubscriptionMutation.js +1 -0
- package/esm/graphql/operations/FileUploadedMutation.js +3 -0
- package/esm/graphql/operations/FlagQuestionAnswerMutation.js +1 -0
- package/esm/graphql/operations/FlagQuestionMutation.js +1 -0
- package/esm/graphql/operations/FlagReviewAnswerMutation.js +1 -0
- package/esm/graphql/operations/FlagReviewMutation.js +1 -0
- package/esm/graphql/operations/GetBrandingQuery.js +7 -0
- package/esm/graphql/operations/GetCartQuery.js +23 -0
- package/esm/graphql/operations/GetCustomerAddressesPageDataQuery.js +13 -0
- package/esm/graphql/operations/GetCustomerBalanceHistoryPageQuery.js +3 -0
- package/esm/graphql/operations/GetCustomerBalanceQuery.js +5 -0
- package/esm/graphql/operations/GetCustomerInfoQuery.js +7 -0
- package/esm/graphql/operations/GetCustomerQuery.js +5 -0
- package/esm/graphql/operations/GetFavoritesQuery.js +19 -0
- package/esm/graphql/operations/GetFileStatusQuery.js +3 -0
- package/esm/graphql/operations/GetGatewaysQuery.js +11 -0
- package/esm/graphql/operations/GetInfoCurrenciesQuery.js +3 -0
- package/esm/graphql/operations/GetLastCartQuery.js +23 -0
- package/esm/graphql/operations/GetOrderQuery.js +27 -0
- package/esm/graphql/operations/GetOrdersPageQuery.js +21 -0
- package/esm/graphql/operations/GetPaymentMethodsPageDataQuery.js +15 -0
- package/esm/graphql/operations/GetProductQuestionsPageQuery.js +7 -0
- package/esm/graphql/operations/GetProductReviewImagesPageQuery.js +5 -0
- package/esm/graphql/operations/GetProductReviewsPageQuery.js +17 -0
- package/esm/graphql/operations/GetProvincesQuery.js +3 -0
- package/esm/graphql/operations/GetQuestionQuery.js +5 -0
- package/esm/graphql/operations/GetReturnCreationInfoQuery.js +33 -0
- package/esm/graphql/operations/GetReturnQuery.js +25 -0
- package/esm/graphql/operations/GetReturnsPageQuery.js +19 -0
- package/esm/graphql/operations/GetReviewDimensionsQuery.js +3 -0
- package/esm/graphql/operations/GetReviewQuery.js +15 -0
- package/esm/graphql/operations/GetReviewSettingsQuery.js +9 -0
- package/esm/graphql/operations/GetShopCurrenciesQuery.js +3 -0
- package/esm/graphql/operations/GetShopQuery.js +5 -0
- package/esm/graphql/operations/GetSubscriptionQuery.js +33 -0
- package/esm/graphql/operations/GetSubscriptionsPageQuery.js +19 -0
- package/esm/graphql/operations/GetVariantPageQuery.js +17 -0
- package/esm/graphql/operations/LoadProductNoCustomerQuery.js +59 -0
- package/esm/graphql/operations/LoadProductQuery.js +63 -0
- package/esm/graphql/operations/ModifyCartMutation.js +23 -0
- package/esm/graphql/operations/ModifyCustomerMutation.js +5 -0
- package/esm/graphql/operations/ModifyFavoriteMutation.js +19 -0
- package/esm/graphql/operations/ModifyProductQuestionAnswerMutation.js +1 -0
- package/esm/graphql/operations/ModifyProductQuestionMutation.js +5 -0
- package/esm/graphql/operations/ModifyProductReviewMutation.js +15 -0
- package/esm/graphql/operations/NewPasswordMutation.js +1 -0
- package/esm/graphql/operations/PauseSubscriptionMutation.js +1 -0
- package/esm/graphql/operations/ResetPasswordMutation.js +1 -0
- package/esm/graphql/operations/ResumeSubscriptionMutation.js +1 -0
- package/esm/graphql/operations/SearchProductsAdvancedQuery.js +21 -0
- package/esm/graphql/operations/SearchProductsQuery.js +17 -0
- package/esm/graphql/operations/SearchQuestionsQuery.js +5 -0
- package/esm/graphql/operations/SearchReviewsQuery.js +15 -0
- package/esm/graphql/operations/SignInMutation.js +1 -0
- package/esm/graphql/operations/SignInViaEmailCompleteMutation.js +1 -0
- package/esm/graphql/operations/SignInViaEmailInitMutation.js +1 -0
- package/esm/graphql/operations/SignUpMutation.js +1 -0
- package/esm/graphql/operations/SkipNextSubscriptionMutation.js +1 -0
- package/esm/graphql/operations/UploadFileMutation.js +1 -0
- package/esm/graphql/operations/VerifyCodeMutation.js +1 -0
- package/esm/graphql/operations/VoteQuestionAnswerMutation.js +1 -0
- package/esm/graphql/operations/VoteQuestionMutation.js +1 -0
- package/esm/graphql/operations/VoteReviewAnswerMutation.js +1 -0
- package/esm/graphql/operations/VoteReviewMutation.js +1 -0
- package/esm/graphql/types.js +1 -0
- package/esm/hierarchicalSearchOption.js +43 -0
- package/esm/idgen.js +4 -0
- package/esm/ignoreQueue.js +45 -0
- package/esm/imageAltProps.js +9 -0
- package/esm/invoiceFormat.js +54 -0
- package/esm/isShippingRequired.js +16 -0
- package/esm/isoStripTrailingZeros.js +3 -0
- package/esm/json/commerce.js +3 -0
- package/esm/json/commerceFileUpload.js +43 -0
- package/esm/json/commerceTypes.js +1 -0
- package/esm/json/common.js +309 -0
- package/esm/json/fetchAllItems.js +51 -0
- package/esm/json/mutator.js +952 -0
- package/esm/json/storefront.js +3 -0
- package/esm/json/storefrontTypes.js +1 -0
- package/esm/lastValue.js +12 -0
- package/esm/lineItemPrice.js +106 -0
- package/esm/loadJWT.js +20 -0
- package/esm/mapInvalidInput.js +27 -0
- package/esm/mapResponseData.js +11 -0
- package/esm/mapResponseMultiData.js +10 -0
- package/esm/meanBy.js +11 -0
- package/esm/media.js +12 -0
- package/esm/modules/advancedSearch.js +132 -0
- package/esm/modules/cart.js +699 -0
- package/esm/modules/config/defaultAdvancedSearchGraphQLConfig.js +4 -0
- package/esm/modules/config/defaultCartGraphQLConfig.js +10 -0
- package/esm/modules/config/defaultProductGraphQLConfig.js +44 -0
- package/esm/modules/config/defaultSearchGraphQLConfig.js +4 -0
- package/esm/modules/customer.js +2198 -0
- package/esm/modules/helpers/cartInitOption.js +18 -0
- package/esm/modules/helpers/cookieConsent.js +29 -0
- package/esm/modules/helpers/customerOauth2.js +53 -0
- package/esm/modules/helpers/getOAuth2Hook.js +48 -0
- package/esm/modules/helpers/hookUpAnalytics.js +44 -0
- package/esm/modules/helpers/loadJWT.js +18 -0
- package/esm/modules/helpers/misc.js +49 -0
- package/esm/modules/imageDialog.js +71 -0
- package/esm/modules/persist.js +49 -0
- package/esm/modules/popupMessage.js +17 -0
- package/esm/modules/product.js +1278 -0
- package/esm/modules/recentlyVisitedProducts.js +70 -0
- package/esm/modules/search.js +103 -0
- package/esm/multiResponseToResponse.js +18 -0
- package/esm/nonNull.js +6 -0
- package/esm/oauthState.js +35 -0
- package/esm/orderShippingAddress.js +3 -0
- package/esm/package.json +3 -0
- package/esm/pender.js +11 -0
- package/esm/percentageOff.js +3 -0
- package/esm/popupConnectQueue.js +55 -0
- package/esm/preact/components/SixDigitInput.js +159 -0
- package/esm/preact/effector.js +69 -0
- package/esm/preact/transition/CSSTransition.js +47 -0
- package/esm/preact/transition/Transition.js +100 -0
- package/esm/preact/translateLocalStatic.js +26 -0
- package/esm/productFiltering.js +164 -0
- package/esm/productSEO.js +46 -0
- package/esm/productSorting.js +89 -0
- package/esm/promiseAll.js +11 -0
- package/esm/promiseLimit.js +32 -0
- package/esm/rdsToInitialScores.js +27 -0
- package/esm/react/components/Portal.js +2 -0
- package/esm/react/components/RootCloseWrapper.js +33 -0
- package/esm/react/components/SixDigitInput.js +158 -0
- package/esm/react/contains.js +10 -0
- package/esm/react/popperBinder.js +71 -0
- package/esm/react/rootClose.js +106 -0
- package/esm/react/translateLocalStatic.js +26 -0
- package/esm/react/useAsyncCachedValue.js +10 -0
- package/esm/refreshTimeout.js +21 -0
- package/esm/remoteAuth.js +52 -0
- package/esm/request.js +323 -0
- package/esm/requestDetails.js +69 -0
- package/esm/rfc3339Normalize.js +6 -0
- package/esm/script.js +157 -0
- package/esm/seo.js +1 -0
- package/esm/shopDomain.js +4 -0
- package/esm/shopLinks.js +47 -0
- package/esm/slate.js +364 -0
- package/esm/sleep.js +3 -0
- package/esm/splitBy.js +17 -0
- package/esm/splitName.js +22 -0
- package/esm/stripZeros.js +9 -0
- package/esm/stripeError.js +53 -0
- package/esm/tailSplit.js +8 -0
- package/esm/tieredPrice.js +28 -0
- package/esm/timeIt.js +8 -0
- package/esm/toMajor.js +4 -0
- package/esm/toMinor.js +4 -0
- package/esm/trace.js +37 -0
- package/esm/translateLocale.js +7 -0
- package/esm/traverse.js +10 -0
- package/esm/truncate.js +17 -0
- package/esm/typedLocalStorage.js +24 -0
- package/esm/variantImage.js +22 -0
- package/esm/variantImageURL.js +9 -0
- package/esm/variantImages.js +15 -0
- package/esm/variantInventory.js +38 -0
- package/esm/variantOptions.js +15 -0
- package/esm/variantPrice.js +92 -0
- package/esm/variantPriceCommerce.js +25 -0
- package/esm/variantTitle.js +5 -0
- package/esm/variantTitleFull.js +7 -0
- package/esm/variantURL.js +5 -0
- package/esm/vendor/popper/index.d.ts +160 -0
- package/esm/vendor/popper/index.js +2657 -0
- package/esm/vendor/popper/index.js.map +1 -0
- package/esm/vendor/popper/package.json +3 -0
- package/esm/websocket.js +169 -0
- package/package.json +92 -0
- package/types/actionLock.d.ts +7 -0
- package/types/addEmptyListItem.d.ts +2 -0
- package/types/aggregateOptions.d.ts +33 -0
- package/types/analytics.d.ts +23 -0
- package/types/analyticsProductData.d.ts +38 -0
- package/types/arrayToDict.d.ts +2 -0
- package/types/asyncModuleWrapper.d.ts +13 -0
- package/types/averageReviewScore.d.ts +28 -0
- package/types/buildconfig.d.ts +13 -0
- package/types/cachedLoader.d.ts +10 -0
- package/types/canonicalVariantURL.d.ts +12 -0
- package/types/cartOperation.d.ts +28 -0
- package/types/categorySEO.d.ts +17 -0
- package/types/commonTypes.d.ts +10 -0
- package/types/compact.d.ts +1 -0
- package/types/configLoader.d.ts +53 -0
- package/types/controlledQueue.d.ts +17 -0
- package/types/convertImageURL.d.ts +9 -0
- package/types/dataLoader.d.ts +301 -0
- package/types/defaultVariant.d.ts +9 -0
- package/types/effector/clearOnChangeAfterDelay.d.ts +2 -0
- package/types/effector/combineEvery.d.ts +2 -0
- package/types/effector/combineSome.d.ts +2 -0
- package/types/effector/debounced.d.ts +2 -0
- package/types/effector/form.d.ts +74 -0
- package/types/effector/hideOnChangeAfterDelay.d.ts +6 -0
- package/types/effector/requestResponse.d.ts +9 -0
- package/types/effector/requestResponseMulti.d.ts +7 -0
- package/types/effector/restoreNamed.d.ts +2 -0
- package/types/effector/split.d.ts +7 -0
- package/types/effector/validator.d.ts +14 -0
- package/types/effector/wrapSignInRequired.d.ts +2 -0
- package/types/exceptions.d.ts +2 -0
- package/types/fetchAllItems.d.ts +25 -0
- package/types/file.d.ts +4 -0
- package/types/fileWebsocket.d.ts +6 -0
- package/types/filterFunc.d.ts +8 -0
- package/types/filterFuncBrand.d.ts +3 -0
- package/types/filterFuncCategory.d.ts +3 -0
- package/types/filterFuncContentBlock.d.ts +3 -0
- package/types/filterFuncCustomer.d.ts +3 -0
- package/types/filterFuncDataFeed.d.ts +8 -0
- package/types/filterFuncOrder.d.ts +3 -0
- package/types/filterFuncPreprocess.d.ts +2 -0
- package/types/filterFuncProduct.d.ts +3 -0
- package/types/filterFuncPurchaseOrder.d.ts +3 -0
- package/types/filterFuncSupplier.d.ts +3 -0
- package/types/filterFuncTransfer.d.ts +3 -0
- package/types/formatAbbrevNumber.d.ts +6 -0
- package/types/formatCurrency.d.ts +44 -0
- package/types/formatToJSX.d.ts +24 -0
- package/types/fulfillmentNumber.d.ts +1 -0
- package/types/generateRandomToken.d.ts +1 -0
- package/types/generateUUID.d.ts +1 -0
- package/types/generated/codes.d.ts +234 -0
- package/types/genericFile.d.ts +57 -0
- package/types/getSalesChannelID.d.ts +1 -0
- package/types/getSessionID.d.ts +1 -0
- package/types/getTimezone.d.ts +1 -0
- package/types/graphql/fragments/Branding.d.ts +2 -0
- package/types/graphql/fragments/BrandingField.d.ts +2 -0
- package/types/graphql/fragments/CartCustomItem.d.ts +2 -0
- package/types/graphql/fragments/CartOrder.d.ts +2 -0
- package/types/graphql/fragments/CartVariant.d.ts +2 -0
- package/types/graphql/fragments/CartVariantFull.d.ts +2 -0
- package/types/graphql/fragments/Category.d.ts +2 -0
- package/types/graphql/fragments/CommonCartVariant.d.ts +2 -0
- package/types/graphql/fragments/Currency.d.ts +2 -0
- package/types/graphql/fragments/CurrencyPrice.d.ts +2 -0
- package/types/graphql/fragments/CustomField.d.ts +2 -0
- package/types/graphql/fragments/CustomFieldObjects.d.ts +2 -0
- package/types/graphql/fragments/Customer.d.ts +2 -0
- package/types/graphql/fragments/CustomerBalance.d.ts +2 -0
- package/types/graphql/fragments/CustomerBalanceHistory.d.ts +2 -0
- package/types/graphql/fragments/CustomerFavorite.d.ts +2 -0
- package/types/graphql/fragments/CustomerFavoriteShort.d.ts +2 -0
- package/types/graphql/fragments/CustomerOAuthProvider.d.ts +2 -0
- package/types/graphql/fragments/CustomerOrderBrief.d.ts +2 -0
- package/types/graphql/fragments/CustomerOrderFulfillment.d.ts +2 -0
- package/types/graphql/fragments/CustomerOrderFull.d.ts +2 -0
- package/types/graphql/fragments/CustomerPaymentSource.d.ts +2 -0
- package/types/graphql/fragments/CustomerReturnBrief.d.ts +2 -0
- package/types/graphql/fragments/CustomerReturnFull.d.ts +2 -0
- package/types/graphql/fragments/CustomerReturnPolicy.d.ts +2 -0
- package/types/graphql/fragments/CustomerSubscriptionBrief.d.ts +2 -0
- package/types/graphql/fragments/CustomerSubscriptionFull.d.ts +2 -0
- package/types/graphql/fragments/File.d.ts +2 -0
- package/types/graphql/fragments/FileForUpload.d.ts +2 -0
- package/types/graphql/fragments/FileNoFallback.d.ts +2 -0
- package/types/graphql/fragments/FullAddress.d.ts +2 -0
- package/types/graphql/fragments/Gateway.d.ts +2 -0
- package/types/graphql/fragments/GatewayManual.d.ts +2 -0
- package/types/graphql/fragments/GatewayPaypal.d.ts +2 -0
- package/types/graphql/fragments/GatewayStripe.d.ts +2 -0
- package/types/graphql/fragments/GatewayTest.d.ts +2 -0
- package/types/graphql/fragments/IPAndUAInfo.d.ts +2 -0
- package/types/graphql/fragments/InfoCountry.d.ts +2 -0
- package/types/graphql/fragments/InfoCountryDedupField.d.ts +2 -0
- package/types/graphql/fragments/InfoCurrency.d.ts +2 -0
- package/types/graphql/fragments/InfoProvince.d.ts +2 -0
- package/types/graphql/fragments/KeyValue.d.ts +2 -0
- package/types/graphql/fragments/LineItemField.d.ts +2 -0
- package/types/graphql/fragments/MediaFile.d.ts +2 -0
- package/types/graphql/fragments/MinCurrencyPrice.d.ts +2 -0
- package/types/graphql/fragments/ProductField.d.ts +2 -0
- package/types/graphql/fragments/ProductFieldSet.d.ts +2 -0
- package/types/graphql/fragments/ProductFlat.d.ts +2 -0
- package/types/graphql/fragments/ProductQuestion.d.ts +2 -0
- package/types/graphql/fragments/ProductQuestionAnswer.d.ts +2 -0
- package/types/graphql/fragments/ProductQuestionPage.d.ts +2 -0
- package/types/graphql/fragments/ProductReview.d.ts +2 -0
- package/types/graphql/fragments/ProductReviewAnswer.d.ts +2 -0
- package/types/graphql/fragments/ProductReviewAverageScore.d.ts +2 -0
- package/types/graphql/fragments/ProductReviewPage.d.ts +2 -0
- package/types/graphql/fragments/ProductReviewScore.d.ts +2 -0
- package/types/graphql/fragments/ProductReviewSurveyAnswer.d.ts +2 -0
- package/types/graphql/fragments/ProductSearchOptionAgg.d.ts +2 -0
- package/types/graphql/fragments/ProductSearchResult.d.ts +2 -0
- package/types/graphql/fragments/ReturnReason.d.ts +2 -0
- package/types/graphql/fragments/ReviewDimension.d.ts +2 -0
- package/types/graphql/fragments/ReviewDimensionSet.d.ts +2 -0
- package/types/graphql/fragments/ReviewImagePage.d.ts +2 -0
- package/types/graphql/fragments/ReviewQuestionProduct.d.ts +2 -0
- package/types/graphql/fragments/ReviewSettings.d.ts +2 -0
- package/types/graphql/fragments/SearchProduct.d.ts +2 -0
- package/types/graphql/fragments/Shop.d.ts +2 -0
- package/types/graphql/fragments/SubscriptionPlan.d.ts +2 -0
- package/types/graphql/fragments/SurveyQuestion.d.ts +2 -0
- package/types/graphql/fragments/TieredPricing.d.ts +2 -0
- package/types/graphql/fragments/TieredPricingTier.d.ts +2 -0
- package/types/graphql/fragments/VariantOption.d.ts +2 -0
- package/types/graphql/operations/ApplyGiftCardMutation.d.ts +3 -0
- package/types/graphql/operations/AuthRequestMutation.d.ts +3 -0
- package/types/graphql/operations/CancelOrderMutation.d.ts +3 -0
- package/types/graphql/operations/CancelSubscriptionMutation.d.ts +3 -0
- package/types/graphql/operations/ConnectOAuth2Mutation.d.ts +3 -0
- package/types/graphql/operations/CreateCartMutation.d.ts +3 -0
- package/types/graphql/operations/CreateFavoriteMutation.d.ts +3 -0
- package/types/graphql/operations/CreateFileMutation.d.ts +3 -0
- package/types/graphql/operations/CreatePaymentSourceMutation.d.ts +3 -0
- package/types/graphql/operations/CreateProductQuestionAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/CreateProductQuestionMutation.d.ts +3 -0
- package/types/graphql/operations/CreateProductReviewMutation.d.ts +3 -0
- package/types/graphql/operations/CreateReturnMutation.d.ts +3 -0
- package/types/graphql/operations/DeleteFavoriteMutation.d.ts +3 -0
- package/types/graphql/operations/DeletePaymentSourceMutation.d.ts +3 -0
- package/types/graphql/operations/DeleteProductQuestionAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/DeleteProductQuestionMutation.d.ts +3 -0
- package/types/graphql/operations/DeleteProductReviewMutation.d.ts +3 -0
- package/types/graphql/operations/DisconnectOAuth2Mutation.d.ts +3 -0
- package/types/graphql/operations/EditSubscriptionMutation.d.ts +3 -0
- package/types/graphql/operations/FileUploadedMutation.d.ts +3 -0
- package/types/graphql/operations/FlagQuestionAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/FlagQuestionMutation.d.ts +3 -0
- package/types/graphql/operations/FlagReviewAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/FlagReviewMutation.d.ts +3 -0
- package/types/graphql/operations/GetBrandingQuery.d.ts +3 -0
- package/types/graphql/operations/GetCartQuery.d.ts +3 -0
- package/types/graphql/operations/GetCustomerAddressesPageDataQuery.d.ts +3 -0
- package/types/graphql/operations/GetCustomerBalanceHistoryPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetCustomerBalanceQuery.d.ts +3 -0
- package/types/graphql/operations/GetCustomerInfoQuery.d.ts +3 -0
- package/types/graphql/operations/GetCustomerQuery.d.ts +3 -0
- package/types/graphql/operations/GetFavoritesQuery.d.ts +3 -0
- package/types/graphql/operations/GetFileStatusQuery.d.ts +3 -0
- package/types/graphql/operations/GetGatewaysQuery.d.ts +3 -0
- package/types/graphql/operations/GetInfoCurrenciesQuery.d.ts +3 -0
- package/types/graphql/operations/GetLastCartQuery.d.ts +3 -0
- package/types/graphql/operations/GetOrderQuery.d.ts +3 -0
- package/types/graphql/operations/GetOrdersPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetPaymentMethodsPageDataQuery.d.ts +3 -0
- package/types/graphql/operations/GetProductQuestionsPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetProductReviewImagesPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetProductReviewsPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetProvincesQuery.d.ts +3 -0
- package/types/graphql/operations/GetQuestionQuery.d.ts +3 -0
- package/types/graphql/operations/GetReturnCreationInfoQuery.d.ts +3 -0
- package/types/graphql/operations/GetReturnQuery.d.ts +3 -0
- package/types/graphql/operations/GetReturnsPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetReviewDimensionsQuery.d.ts +3 -0
- package/types/graphql/operations/GetReviewQuery.d.ts +3 -0
- package/types/graphql/operations/GetReviewSettingsQuery.d.ts +3 -0
- package/types/graphql/operations/GetShopCurrenciesQuery.d.ts +3 -0
- package/types/graphql/operations/GetShopQuery.d.ts +3 -0
- package/types/graphql/operations/GetSubscriptionQuery.d.ts +3 -0
- package/types/graphql/operations/GetSubscriptionsPageQuery.d.ts +3 -0
- package/types/graphql/operations/GetVariantPageQuery.d.ts +3 -0
- package/types/graphql/operations/LoadProductNoCustomerQuery.d.ts +3 -0
- package/types/graphql/operations/LoadProductQuery.d.ts +3 -0
- package/types/graphql/operations/ModifyCartMutation.d.ts +3 -0
- package/types/graphql/operations/ModifyCustomerMutation.d.ts +3 -0
- package/types/graphql/operations/ModifyFavoriteMutation.d.ts +3 -0
- package/types/graphql/operations/ModifyProductQuestionAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/ModifyProductQuestionMutation.d.ts +3 -0
- package/types/graphql/operations/ModifyProductReviewMutation.d.ts +3 -0
- package/types/graphql/operations/NewPasswordMutation.d.ts +3 -0
- package/types/graphql/operations/PauseSubscriptionMutation.d.ts +3 -0
- package/types/graphql/operations/ResetPasswordMutation.d.ts +3 -0
- package/types/graphql/operations/ResumeSubscriptionMutation.d.ts +3 -0
- package/types/graphql/operations/SearchProductsAdvancedQuery.d.ts +3 -0
- package/types/graphql/operations/SearchProductsQuery.d.ts +3 -0
- package/types/graphql/operations/SearchQuestionsQuery.d.ts +3 -0
- package/types/graphql/operations/SearchReviewsQuery.d.ts +3 -0
- package/types/graphql/operations/SignInMutation.d.ts +3 -0
- package/types/graphql/operations/SignInViaEmailCompleteMutation.d.ts +3 -0
- package/types/graphql/operations/SignInViaEmailInitMutation.d.ts +3 -0
- package/types/graphql/operations/SignUpMutation.d.ts +3 -0
- package/types/graphql/operations/SkipNextSubscriptionMutation.d.ts +3 -0
- package/types/graphql/operations/UploadFileMutation.d.ts +3 -0
- package/types/graphql/operations/VerifyCodeMutation.d.ts +3 -0
- package/types/graphql/operations/VoteQuestionAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/VoteQuestionMutation.d.ts +3 -0
- package/types/graphql/operations/VoteReviewAnswerMutation.d.ts +3 -0
- package/types/graphql/operations/VoteReviewMutation.d.ts +3 -0
- package/types/graphql/types.d.ts +2471 -0
- package/types/hierarchicalSearchOption.d.ts +14 -0
- package/types/idgen.d.ts +1 -0
- package/types/ignoreQueue.d.ts +10 -0
- package/types/imageAltProps.d.ts +11 -0
- package/types/invoiceFormat.d.ts +32 -0
- package/types/isShippingRequired.d.ts +14 -0
- package/types/isoStripTrailingZeros.d.ts +1 -0
- package/types/json/commerce.d.ts +3 -0
- package/types/json/commerceFileUpload.d.ts +20 -0
- package/types/json/commerceTypes.d.ts +15422 -0
- package/types/json/common.d.ts +81 -0
- package/types/json/fetchAllItems.d.ts +15 -0
- package/types/json/mutator.d.ts +238 -0
- package/types/json/storefront.d.ts +3 -0
- package/types/json/storefrontTypes.d.ts +5059 -0
- package/types/lastValue.d.ts +10 -0
- package/types/lineItemPrice.d.ts +18 -0
- package/types/loadJWT.d.ts +1 -0
- package/types/mapInvalidInput.d.ts +15 -0
- package/types/mapResponseData.d.ts +3 -0
- package/types/mapResponseMultiData.d.ts +2 -0
- package/types/meanBy.d.ts +1 -0
- package/types/media.d.ts +3 -0
- package/types/modules/advancedSearch.d.ts +78 -0
- package/types/modules/cart.d.ts +263 -0
- package/types/modules/config/defaultAdvancedSearchGraphQLConfig.d.ts +3 -0
- package/types/modules/config/defaultCartGraphQLConfig.d.ts +6 -0
- package/types/modules/config/defaultProductGraphQLConfig.d.ts +23 -0
- package/types/modules/config/defaultSearchGraphQLConfig.d.ts +3 -0
- package/types/modules/customer.d.ts +624 -0
- package/types/modules/helpers/cartInitOption.d.ts +2 -0
- package/types/modules/helpers/cookieConsent.d.ts +4 -0
- package/types/modules/helpers/customerOauth2.d.ts +19 -0
- package/types/modules/helpers/getOAuth2Hook.d.ts +22 -0
- package/types/modules/helpers/hookUpAnalytics.d.ts +21 -0
- package/types/modules/helpers/loadJWT.d.ts +1 -0
- package/types/modules/helpers/misc.d.ts +14 -0
- package/types/modules/imageDialog.d.ts +31 -0
- package/types/modules/persist.d.ts +13 -0
- package/types/modules/popupMessage.d.ts +9 -0
- package/types/modules/product.d.ts +320 -0
- package/types/modules/recentlyVisitedProducts.d.ts +25 -0
- package/types/modules/search.d.ts +54 -0
- package/types/multiResponseToResponse.d.ts +2 -0
- package/types/nonNull.d.ts +1 -0
- package/types/oauthState.d.ts +3 -0
- package/types/orderShippingAddress.d.ts +6 -0
- package/types/pender.d.ts +5 -0
- package/types/percentageOff.d.ts +1 -0
- package/types/popupConnectQueue.d.ts +41 -0
- package/types/preact/components/SixDigitInput.d.ts +28 -0
- package/types/preact/effector.d.ts +8 -0
- package/types/preact/transition/CSSTransition.d.ts +8 -0
- package/types/preact/transition/Transition.d.ts +30 -0
- package/types/preact/translateLocalStatic.d.ts +4 -0
- package/types/productFiltering.d.ts +58 -0
- package/types/productSEO.d.ts +59 -0
- package/types/productSorting.d.ts +35 -0
- package/types/promiseAll.d.ts +5 -0
- package/types/promiseLimit.d.ts +13 -0
- package/types/rdsToInitialScores.d.ts +26 -0
- package/types/react/components/Portal.d.ts +2 -0
- package/types/react/components/RootCloseWrapper.d.ts +18 -0
- package/types/react/components/SixDigitInput.d.ts +27 -0
- package/types/react/contains.d.ts +1 -0
- package/types/react/popperBinder.d.ts +23 -0
- package/types/react/rootClose.d.ts +18 -0
- package/types/react/translateLocalStatic.d.ts +4 -0
- package/types/react/useAsyncCachedValue.d.ts +2 -0
- package/types/refreshTimeout.d.ts +5 -0
- package/types/remoteAuth.d.ts +14 -0
- package/types/request.d.ts +104 -0
- package/types/requestDetails.d.ts +16 -0
- package/types/rfc3339Normalize.d.ts +1 -0
- package/types/script.d.ts +36 -0
- package/types/seo.d.ts +5 -0
- package/types/shopDomain.d.ts +7 -0
- package/types/shopLinks.d.ts +14 -0
- package/types/slate.d.ts +47 -0
- package/types/sleep.d.ts +1 -0
- package/types/splitBy.d.ts +1 -0
- package/types/splitName.d.ts +2 -0
- package/types/stripZeros.d.ts +1 -0
- package/types/stripeError.d.ts +14 -0
- package/types/tailSplit.d.ts +1 -0
- package/types/tieredPrice.d.ts +2 -0
- package/types/timeIt.d.ts +1 -0
- package/types/toMajor.d.ts +8 -0
- package/types/toMinor.d.ts +8 -0
- package/types/trace.d.ts +17 -0
- package/types/translateLocale.d.ts +2 -0
- package/types/traverse.d.ts +1 -0
- package/types/truncate.d.ts +7 -0
- package/types/typedLocalStorage.d.ts +3 -0
- package/types/variantImage.d.ts +16 -0
- package/types/variantImageURL.d.ts +25 -0
- package/types/variantImages.d.ts +11 -0
- package/types/variantInventory.d.ts +14 -0
- package/types/variantOptions.d.ts +18 -0
- package/types/variantPrice.d.ts +37 -0
- package/types/variantPriceCommerce.d.ts +26 -0
- package/types/variantTitle.d.ts +7 -0
- package/types/variantTitleFull.d.ts +11 -0
- package/types/variantURL.d.ts +7 -0
- package/types/websocket.d.ts +33 -0
|
@@ -0,0 +1,2198 @@
|
|
|
1
|
+
import jwtDecode from "jwt-decode";
|
|
2
|
+
import { combine, createEffect, createEvent, createStore, forward, guard, restore, sample, } from "effector";
|
|
3
|
+
import applyGiftCardMutation from "../graphql/operations/ApplyGiftCardMutation.js";
|
|
4
|
+
import cancelOrderMutation from "../graphql/operations/CancelOrderMutation.js";
|
|
5
|
+
import cancelSubscriptionMutation from "../graphql/operations/CancelSubscriptionMutation.js";
|
|
6
|
+
import connectOAuth2Mutation from "../graphql/operations/ConnectOAuth2Mutation.js";
|
|
7
|
+
import createFavoriteMutation from "../graphql/operations/CreateFavoriteMutation.js";
|
|
8
|
+
import createPaymentSourceMutation from "../graphql/operations/CreatePaymentSourceMutation.js";
|
|
9
|
+
import createReturnMutation from "../graphql/operations/CreateReturnMutation.js";
|
|
10
|
+
import deleteFavoriteMutation from "../graphql/operations/DeleteFavoriteMutation.js";
|
|
11
|
+
import deletePaymentSourceMutation from "../graphql/operations/DeletePaymentSourceMutation.js";
|
|
12
|
+
import disconnectOAuth2Mutation from "../graphql/operations/DisconnectOAuth2Mutation.js";
|
|
13
|
+
import editSubscriptionMutation from "../graphql/operations/EditSubscriptionMutation.js";
|
|
14
|
+
import getCustomerAddressesPageDataQuery from "../graphql/operations/GetCustomerAddressesPageDataQuery.js";
|
|
15
|
+
import getCustomerBalanceHistoryPageQuery from "../graphql/operations/GetCustomerBalanceHistoryPageQuery.js";
|
|
16
|
+
import getCustomerBalanceQuery from "../graphql/operations/GetCustomerBalanceQuery.js";
|
|
17
|
+
import getCustomerInfoQuery from "../graphql/operations/GetCustomerInfoQuery.js";
|
|
18
|
+
import getCustomerQuery from "../graphql/operations/GetCustomerQuery.js";
|
|
19
|
+
import getFavoritesQuery from "../graphql/operations/GetFavoritesQuery.js";
|
|
20
|
+
import getOrderQuery from "../graphql/operations/GetOrderQuery.js";
|
|
21
|
+
import getOrdersPageQuery from "../graphql/operations/GetOrdersPageQuery.js";
|
|
22
|
+
import getPaymentMethodsPageDataQuery from "../graphql/operations/GetPaymentMethodsPageDataQuery.js";
|
|
23
|
+
import getProvincesQuery from "../graphql/operations/GetProvincesQuery.js";
|
|
24
|
+
import getReturnCreationInfoQuery from "../graphql/operations/GetReturnCreationInfoQuery.js";
|
|
25
|
+
import getReturnQuery from "../graphql/operations/GetReturnQuery.js";
|
|
26
|
+
import getReturnsPageQuery from "../graphql/operations/GetReturnsPageQuery.js";
|
|
27
|
+
import getSubscriptionQuery from "../graphql/operations/GetSubscriptionQuery.js";
|
|
28
|
+
import getSubscriptionsPageQuery from "../graphql/operations/GetSubscriptionsPageQuery.js";
|
|
29
|
+
import modifyCustomerMutation from "../graphql/operations/ModifyCustomerMutation.js";
|
|
30
|
+
import modifyFavoriteMutation from "../graphql/operations/ModifyFavoriteMutation.js";
|
|
31
|
+
import newPasswordMutation from "../graphql/operations/NewPasswordMutation.js";
|
|
32
|
+
import pauseSubscriptionMutation from "../graphql/operations/PauseSubscriptionMutation.js";
|
|
33
|
+
import resetPasswordMutation from "../graphql/operations/ResetPasswordMutation.js";
|
|
34
|
+
import resumeSubscriptionMutation from "../graphql/operations/ResumeSubscriptionMutation.js";
|
|
35
|
+
import signInMutation from "../graphql/operations/SignInMutation.js";
|
|
36
|
+
import signInViaEmailCompleteMutation from "../graphql/operations/SignInViaEmailCompleteMutation.js";
|
|
37
|
+
import signInViaEmailInitMutation from "../graphql/operations/SignInViaEmailInitMutation.js";
|
|
38
|
+
import signUpMutation from "../graphql/operations/SignUpMutation.js";
|
|
39
|
+
import skipNextSubscriptionMutation from "../graphql/operations/SkipNextSubscriptionMutation.js";
|
|
40
|
+
import verifyCodeMutation from "../graphql/operations/VerifyCodeMutation.js";
|
|
41
|
+
import { ErrorCode } from "../generated/codes.js";
|
|
42
|
+
import { request, requestMulti } from "../request.js";
|
|
43
|
+
import { mapInvalidInput } from "../mapInvalidInput.js";
|
|
44
|
+
import { matchCVCErrorFromRR, matchExpiryErrorFromRR, matchNumberErrorFromRR, } from "../stripeError.js";
|
|
45
|
+
import { validEmail, validMaxLength160, validMaxLength190, validMaxLength250, validMaxLength32, validMaxLength80, validNonEmpty, } from "../effector/validator.js";
|
|
46
|
+
import { addEmptyListItem } from "../addEmptyListItem.js";
|
|
47
|
+
import { combineEvery } from "../effector/combineEvery.js";
|
|
48
|
+
import { combineSome } from "../effector/combineSome.js";
|
|
49
|
+
import { compact } from "../compact.js";
|
|
50
|
+
import { createBooleanField, createEnumField, createForm, createFormWithCustomError, createStringField, } from "../effector/form.js";
|
|
51
|
+
import { deserialize, serialize } from "./persist.js";
|
|
52
|
+
import { generateRandomToken } from "../generateRandomToken.js";
|
|
53
|
+
import { getTimezone } from "../getTimezone.js";
|
|
54
|
+
import { lastValue } from "../lastValue.js";
|
|
55
|
+
import { mapResponseData } from "../mapResponseData.js";
|
|
56
|
+
import { multiResponseToResponse } from "../multiResponseToResponse.js";
|
|
57
|
+
import { nonNull } from "../nonNull.js";
|
|
58
|
+
import { requestResponseSplit, requestResponseSplitFirst } from "../effector/requestResponse.js";
|
|
59
|
+
import { splitMap } from "../effector/split.js";
|
|
60
|
+
async function getCustomerInfo(shopID, id, opts) {
|
|
61
|
+
if (!opts?.authToken)
|
|
62
|
+
return null;
|
|
63
|
+
const resp = await requestMulti(getCustomerInfoQuery)({ shopID, id }, opts);
|
|
64
|
+
if (resp.kind === "data_or_error" && resp.data) {
|
|
65
|
+
const { customer, favorites } = resp.data;
|
|
66
|
+
if (customer && favorites) {
|
|
67
|
+
return {
|
|
68
|
+
customer: customer[0],
|
|
69
|
+
favorites: compact(favorites.map((f) => f.variant
|
|
70
|
+
? {
|
|
71
|
+
id: f.id,
|
|
72
|
+
variantID: f.variant.id,
|
|
73
|
+
inventoryNotification: f.inventory_notification,
|
|
74
|
+
priceNotification: f.price_notification,
|
|
75
|
+
}
|
|
76
|
+
: undefined)),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
export function createVariantMap(order) {
|
|
83
|
+
const out = {};
|
|
84
|
+
for (const li of order.line_items) {
|
|
85
|
+
if (!li.variant)
|
|
86
|
+
continue;
|
|
87
|
+
out[li.variant.id] = li.variant;
|
|
88
|
+
if (li.variant.type === "bundle" && li.variant.bundle_line_items.length > 0) {
|
|
89
|
+
for (const bli of li.variant.bundle_line_items) {
|
|
90
|
+
if (!bli.variant)
|
|
91
|
+
continue;
|
|
92
|
+
out[bli.variant.id] = bli.variant;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
//===================================================================================================================
|
|
99
|
+
//===================================================================================================================
|
|
100
|
+
//===================================================================================================================
|
|
101
|
+
function formToBillingDetails(form) {
|
|
102
|
+
return {
|
|
103
|
+
name: form.name,
|
|
104
|
+
address: {
|
|
105
|
+
line1: form.address,
|
|
106
|
+
line2: "",
|
|
107
|
+
city: form.city,
|
|
108
|
+
postal_code: form.zip,
|
|
109
|
+
country: form.country,
|
|
110
|
+
state: form.province,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
//===================================================================================================================
|
|
115
|
+
//===================================================================================================================
|
|
116
|
+
//===================================================================================================================
|
|
117
|
+
function createAvailableProvincesLogic(binding, validators) {
|
|
118
|
+
// note that logic is only correct if fields start with these values: [], "", ""
|
|
119
|
+
const availableProvinces = createStore([]);
|
|
120
|
+
const country = createStringField("country", "", validators);
|
|
121
|
+
const province = createStringField("province", "", validators);
|
|
122
|
+
const clearProvince = createEvent();
|
|
123
|
+
// really clear province, this ignores initialValue
|
|
124
|
+
province.value.on(clearProvince, () => "");
|
|
125
|
+
province.touched.reset(clearProvince);
|
|
126
|
+
// once "availableProvinces" changes, check if "province" is valid, if not -> clear "province"
|
|
127
|
+
guard({
|
|
128
|
+
source: availableProvinces,
|
|
129
|
+
filter: combine(province.value, availableProvinces, (province, availableProvinces) => !availableProvinces.find((p) => p.code === province)),
|
|
130
|
+
target: clearProvince,
|
|
131
|
+
});
|
|
132
|
+
// "getProvincesFx" and its logic
|
|
133
|
+
const getProvincesFx = createEffect(lastValue(async (p) => {
|
|
134
|
+
const { shopID, opts } = p.config;
|
|
135
|
+
return request(getProvincesQuery)({ shopID, countryCode: p.data }, opts);
|
|
136
|
+
}));
|
|
137
|
+
{
|
|
138
|
+
const getProvincesLastValue = getProvincesFx.doneData.filterMap((v) => v.kind === "resolved" ? v.value : undefined);
|
|
139
|
+
const getProvincesResult = requestResponseSplit(getProvincesLastValue);
|
|
140
|
+
// success, apply "availableProvinces"
|
|
141
|
+
availableProvinces.on(getProvincesResult.data, (_, v) => v);
|
|
142
|
+
// failure, reset "availableProvinces" and report error
|
|
143
|
+
availableProvinces.reset(getProvincesResult.error);
|
|
144
|
+
forward({
|
|
145
|
+
from: getProvincesResult.error,
|
|
146
|
+
to: binding.unexpectedError,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
// on "country" changes
|
|
150
|
+
// 1. if "country" is empty
|
|
151
|
+
// -> clear "availableProvinces"
|
|
152
|
+
// -> clear "province" field
|
|
153
|
+
// 2. if "country" is not empty
|
|
154
|
+
// -> run "getProvincesFx", it will change "availableProvinces" once resolved
|
|
155
|
+
const countryChanged = sample(binding.internalConfig, country.value.updates, (config, data) => ({
|
|
156
|
+
config,
|
|
157
|
+
data,
|
|
158
|
+
}));
|
|
159
|
+
availableProvinces.reset(country.value.updates.filterMap((v) => (!v ? true : undefined)));
|
|
160
|
+
guard({
|
|
161
|
+
source: countryChanged,
|
|
162
|
+
filter: (v) => !!v.data,
|
|
163
|
+
target: getProvincesFx,
|
|
164
|
+
});
|
|
165
|
+
guard({
|
|
166
|
+
source: countryChanged,
|
|
167
|
+
filter: (v) => !v.data,
|
|
168
|
+
target: clearProvince,
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
availableProvinces,
|
|
172
|
+
country,
|
|
173
|
+
province,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
export function isSamePageParam(a, b) {
|
|
177
|
+
// TODO: probably I can just remove CommonPageParam part and do a deep comparison
|
|
178
|
+
if (a.kind === "order" && b.kind === "order") {
|
|
179
|
+
return a.orderID === b.orderID;
|
|
180
|
+
}
|
|
181
|
+
else if (a.kind === "create_return" && b.kind === "create_return") {
|
|
182
|
+
return a.orderID === b.orderID;
|
|
183
|
+
}
|
|
184
|
+
else if (a.kind === "subscription" && b.kind === "subscription") {
|
|
185
|
+
return a.subscriptionID === b.subscriptionID;
|
|
186
|
+
}
|
|
187
|
+
else if (a.kind === "return" && b.kind === "return") {
|
|
188
|
+
return a.returnID === b.returnID;
|
|
189
|
+
}
|
|
190
|
+
else if (a.kind === "confirm" && b.kind === "confirm") {
|
|
191
|
+
return a.token === b.token;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
return a.kind === b.kind;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function defineInit(binding, fn) {
|
|
198
|
+
const event = createEvent();
|
|
199
|
+
const load = createEvent();
|
|
200
|
+
const loadFx = createEffect((p) => fn(p.config, p.param));
|
|
201
|
+
const loadParam = load.map((p) => p.param);
|
|
202
|
+
const { initPageSuccess: success, initPageFailure: failure } = splitRequestResponseData(loadFx.doneData);
|
|
203
|
+
guard({
|
|
204
|
+
source: sample(binding.internalConfig, load, (config, param) => ({ config, param })),
|
|
205
|
+
filter: binding.everythingIdle,
|
|
206
|
+
target: loadFx,
|
|
207
|
+
});
|
|
208
|
+
forward({
|
|
209
|
+
from: success,
|
|
210
|
+
to: event,
|
|
211
|
+
});
|
|
212
|
+
forward({
|
|
213
|
+
from: failure,
|
|
214
|
+
to: binding.unexpectedError,
|
|
215
|
+
});
|
|
216
|
+
return {
|
|
217
|
+
event,
|
|
218
|
+
load,
|
|
219
|
+
loaded: sample(loadParam, success),
|
|
220
|
+
pending: loadFx.pending,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function defineInitBlank(binding) {
|
|
224
|
+
return defineInit(binding, async () => ({ kind: "data", data: null }));
|
|
225
|
+
}
|
|
226
|
+
//===================================================================================================================
|
|
227
|
+
//===================================================================================================================
|
|
228
|
+
//===================================================================================================================
|
|
229
|
+
function splitRequestResponseData(source) {
|
|
230
|
+
const initPageSuccess = createEvent();
|
|
231
|
+
const initPageFailure = createEvent();
|
|
232
|
+
splitMap(source)
|
|
233
|
+
.map((v) => (v.kind === "data" ? v.data : undefined), initPageSuccess)
|
|
234
|
+
.fallback(initPageFailure);
|
|
235
|
+
return { initPageSuccess, initPageFailure };
|
|
236
|
+
}
|
|
237
|
+
//===================================================================================================================
|
|
238
|
+
//===================================================================================================================
|
|
239
|
+
//===================================================================================================================
|
|
240
|
+
// pages you're not allowed to be in, while being logged in
|
|
241
|
+
const disallowedAuthPages = {
|
|
242
|
+
signup: true,
|
|
243
|
+
signin: true,
|
|
244
|
+
};
|
|
245
|
+
// it's not allowed to store these pages as lastAuthPage
|
|
246
|
+
const disallowedLastAuthPages = {
|
|
247
|
+
...disallowedAuthPages,
|
|
248
|
+
reset_password: true,
|
|
249
|
+
order: true,
|
|
250
|
+
create_return: true,
|
|
251
|
+
subscription: true,
|
|
252
|
+
return: true,
|
|
253
|
+
confirm: true,
|
|
254
|
+
};
|
|
255
|
+
// only pages you're allowed to be in, while NOT being logged in
|
|
256
|
+
const allowedNoAuthPages = {
|
|
257
|
+
signup: true,
|
|
258
|
+
signin: true,
|
|
259
|
+
confirm: true,
|
|
260
|
+
reset_password: true,
|
|
261
|
+
};
|
|
262
|
+
function shouldRedirect(jwt, pp, lastAuthPage) {
|
|
263
|
+
if (jwt) {
|
|
264
|
+
if (disallowedAuthPages[pp.kind]) {
|
|
265
|
+
return lastAuthPage
|
|
266
|
+
? { ...lastAuthPage, action: pp.action === "pop" ? "pop_redirect" : "push_redirect" }
|
|
267
|
+
: { kind: "orders", action: pp.action === "pop" ? "pop_redirect" : "push_redirect" };
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
if (!allowedNoAuthPages[pp.kind]) {
|
|
272
|
+
return { kind: "signin", action: pp.action === "pop" ? "pop_redirect" : "push_redirect" };
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
//===================================================================================================================
|
|
277
|
+
//===================================================================================================================
|
|
278
|
+
//===================================================================================================================
|
|
279
|
+
function createFormToggleState(binding, form) {
|
|
280
|
+
const toggleForReal = createEvent();
|
|
281
|
+
const toggleFormVisibility = createEvent();
|
|
282
|
+
const isFormVisible = createStore(false);
|
|
283
|
+
// form ui logic
|
|
284
|
+
{
|
|
285
|
+
guard({
|
|
286
|
+
source: toggleFormVisibility,
|
|
287
|
+
filter: binding.everythingIdle,
|
|
288
|
+
target: toggleForReal,
|
|
289
|
+
});
|
|
290
|
+
// toggle form visibility
|
|
291
|
+
isFormVisible.on(toggleForReal, (v) => !v);
|
|
292
|
+
// when form visibility changes, on false => true transition reset the form also
|
|
293
|
+
forward({
|
|
294
|
+
from: isFormVisible.updates.filterMap((v) => v || undefined),
|
|
295
|
+
to: form.reset,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
toggleFormVisibility,
|
|
300
|
+
isFormVisible,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
function handleFormFailure(c, ...prefixMaps) {
|
|
304
|
+
const source = c.source || createEvent();
|
|
305
|
+
sample({
|
|
306
|
+
source,
|
|
307
|
+
clock: c.form.errorPropagationFailed,
|
|
308
|
+
target: c.unexpectedError,
|
|
309
|
+
});
|
|
310
|
+
splitMap(source)
|
|
311
|
+
.map((e) => mapInvalidInput(e, ...prefixMaps), c.form.propagateErrors)
|
|
312
|
+
.fallback(c.unexpectedError);
|
|
313
|
+
return source;
|
|
314
|
+
}
|
|
315
|
+
//===================================================================================================================
|
|
316
|
+
//===================================================================================================================
|
|
317
|
+
//===================================================================================================================
|
|
318
|
+
function createSignupPageGraph(binding) {
|
|
319
|
+
const init = defineInitBlank(binding);
|
|
320
|
+
const form = createForm({
|
|
321
|
+
name: createStringField("name", "", [validNonEmpty, validMaxLength250]),
|
|
322
|
+
email: createStringField("email", "", [validNonEmpty, validEmail, validMaxLength250]),
|
|
323
|
+
password: createStringField("password", "", [validNonEmpty]),
|
|
324
|
+
accepts_marketing: createBooleanField("accepts_marketing", false),
|
|
325
|
+
});
|
|
326
|
+
forward({
|
|
327
|
+
from: init.event,
|
|
328
|
+
to: form.reset,
|
|
329
|
+
});
|
|
330
|
+
const signupFx = createEffect(async (p) => {
|
|
331
|
+
const { shopID, opts } = p.config;
|
|
332
|
+
return request(signUpMutation)({ shopID, data: p.data }, opts);
|
|
333
|
+
});
|
|
334
|
+
guard({
|
|
335
|
+
source: sample(binding.internalConfig, form.submitted, (config, data) => ({
|
|
336
|
+
config,
|
|
337
|
+
data: { ...data, timezone_hint: getTimezone() },
|
|
338
|
+
})),
|
|
339
|
+
filter: binding.everythingIdle,
|
|
340
|
+
target: signupFx,
|
|
341
|
+
});
|
|
342
|
+
const { data: signupData, error: signupError } = requestResponseSplit(signupFx.doneData);
|
|
343
|
+
// success
|
|
344
|
+
forward({
|
|
345
|
+
from: signupData.filterMap((v) => v[0].token || undefined),
|
|
346
|
+
to: binding.setJWT,
|
|
347
|
+
});
|
|
348
|
+
// failure
|
|
349
|
+
handleFormFailure({ source: signupError, form, unexpectedError: binding.unexpectedError }, { from: "[0]." });
|
|
350
|
+
return {
|
|
351
|
+
init,
|
|
352
|
+
form,
|
|
353
|
+
somethingIsPending: combineSome(init.pending, signupFx.pending),
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
//===================================================================================================================
|
|
357
|
+
//===================================================================================================================
|
|
358
|
+
//===================================================================================================================
|
|
359
|
+
function createResetPasswordPageGraph(binding) {
|
|
360
|
+
const init = defineInitBlank(binding);
|
|
361
|
+
// forms, we use shared fields here
|
|
362
|
+
const resetPasswordForm = createFormWithCustomError({
|
|
363
|
+
email: createStringField("email", "", [validNonEmpty, validEmail, validMaxLength250]),
|
|
364
|
+
}, null);
|
|
365
|
+
const verifyCodeForm = createFormWithCustomError({
|
|
366
|
+
code: createStringField("code", "", [validNonEmpty]),
|
|
367
|
+
}, null);
|
|
368
|
+
const newPasswordForm = createForm({
|
|
369
|
+
password: createStringField("password", "", [validNonEmpty]),
|
|
370
|
+
});
|
|
371
|
+
const setStep = createEvent();
|
|
372
|
+
const currentStep = restore(setStep, { kind: "step1", form: resetPasswordForm });
|
|
373
|
+
forward({
|
|
374
|
+
from: init.event,
|
|
375
|
+
to: [resetPasswordForm.reset, verifyCodeForm.reset, newPasswordForm.reset],
|
|
376
|
+
});
|
|
377
|
+
currentStep.reset(init.event);
|
|
378
|
+
// API requests
|
|
379
|
+
const noAuthConfig = binding.internalConfig.map((v) => ({
|
|
380
|
+
...v,
|
|
381
|
+
opts: {
|
|
382
|
+
...v.opts,
|
|
383
|
+
authToken: undefined,
|
|
384
|
+
},
|
|
385
|
+
}));
|
|
386
|
+
const resetPasswordFx = createEffect(async (p) => {
|
|
387
|
+
const { shopID, opts } = p.config;
|
|
388
|
+
return request(resetPasswordMutation)({ shopID, data: p.data }, opts);
|
|
389
|
+
});
|
|
390
|
+
const verifyCodeFx = createEffect(async (p) => {
|
|
391
|
+
const { shopID, opts } = p.config;
|
|
392
|
+
return request(verifyCodeMutation)({ shopID, data: p.data }, opts);
|
|
393
|
+
});
|
|
394
|
+
const newPasswordFx = createEffect(async (p) => {
|
|
395
|
+
const { shopID, opts } = p.config;
|
|
396
|
+
return request(newPasswordMutation)({ shopID, data: p.data }, opts);
|
|
397
|
+
});
|
|
398
|
+
// wire each form to its own API request
|
|
399
|
+
const step2Submitted = sample(resetPasswordForm.submitted, verifyCodeForm.submitted, (a, b) => ({ ...a, ...b }));
|
|
400
|
+
const step3Submitted = sample(step2Submitted, newPasswordForm.submitted, (a, b) => ({ ...a, ...b }));
|
|
401
|
+
guard({
|
|
402
|
+
source: sample(noAuthConfig, resetPasswordForm.submitted, (config, data) => ({ config, data })),
|
|
403
|
+
filter: binding.everythingIdle,
|
|
404
|
+
target: resetPasswordFx,
|
|
405
|
+
});
|
|
406
|
+
guard({
|
|
407
|
+
source: sample(noAuthConfig, step2Submitted, (config, data) => ({ config, data })),
|
|
408
|
+
filter: binding.everythingIdle,
|
|
409
|
+
target: verifyCodeFx,
|
|
410
|
+
});
|
|
411
|
+
guard({
|
|
412
|
+
source: sample(noAuthConfig, step3Submitted, (config, data) => ({ config, data })),
|
|
413
|
+
filter: binding.everythingIdle,
|
|
414
|
+
target: newPasswordFx,
|
|
415
|
+
});
|
|
416
|
+
// split API response results
|
|
417
|
+
const resetPasswordResult = requestResponseSplit(resetPasswordFx.doneData);
|
|
418
|
+
const verifyCodeResult = requestResponseSplit(verifyCodeFx.doneData);
|
|
419
|
+
const newPasswordResult = requestResponseSplit(newPasswordFx.doneData);
|
|
420
|
+
// SUCCESS
|
|
421
|
+
{
|
|
422
|
+
// form 1 => form 2
|
|
423
|
+
forward({
|
|
424
|
+
from: resetPasswordResult.data.map(() => ({ kind: "step2", form: verifyCodeForm })),
|
|
425
|
+
to: setStep,
|
|
426
|
+
});
|
|
427
|
+
// form 2 => form 3
|
|
428
|
+
forward({
|
|
429
|
+
from: verifyCodeResult.data.map(() => ({ kind: "step3", form: newPasswordForm })),
|
|
430
|
+
to: setStep,
|
|
431
|
+
});
|
|
432
|
+
// form 3 => drop auth, go to signin page
|
|
433
|
+
forward({
|
|
434
|
+
from: newPasswordResult.data.map(() => ""),
|
|
435
|
+
to: binding.setJWT,
|
|
436
|
+
});
|
|
437
|
+
forward({
|
|
438
|
+
from: newPasswordResult.data.map(() => ({ kind: "signin", action: "push" })),
|
|
439
|
+
to: binding.goTo,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
// FAILURE
|
|
443
|
+
{
|
|
444
|
+
// form 1
|
|
445
|
+
splitMap(resetPasswordResult.error)
|
|
446
|
+
.map((e) => e.kind === "error" && e.error.apiError?.code === ErrorCode.TryAgainLater ? "try_again_later" : undefined, resetPasswordForm.setError)
|
|
447
|
+
.fallback(handleFormFailure({ form: resetPasswordForm, unexpectedError: binding.unexpectedError }));
|
|
448
|
+
// form 2
|
|
449
|
+
splitMap(verifyCodeResult.error)
|
|
450
|
+
.map((e) => (e.kind === "error" && e.error.apiError?.code === ErrorCode.NotFound ? "not_found" : undefined), verifyCodeForm.setError)
|
|
451
|
+
.fallback(handleFormFailure({ form: verifyCodeForm, unexpectedError: binding.unexpectedError }));
|
|
452
|
+
// form 3
|
|
453
|
+
handleFormFailure({
|
|
454
|
+
source: newPasswordResult.error,
|
|
455
|
+
form: newPasswordForm,
|
|
456
|
+
unexpectedError: binding.unexpectedError,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
init,
|
|
461
|
+
currentStep,
|
|
462
|
+
somethingIsPending: combineSome(init.pending, resetPasswordFx.pending, verifyCodeFx.pending, newPasswordFx.pending),
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
//===================================================================================================================
|
|
466
|
+
//===================================================================================================================
|
|
467
|
+
//===================================================================================================================
|
|
468
|
+
function createPaymentMethodsPageGraph(binding) {
|
|
469
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
470
|
+
const { shopID, opts } = config;
|
|
471
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
472
|
+
return multiResponseToResponse(await requestMulti(getPaymentMethodsPageDataQuery)({ shopID, customerID: jwt.customer_id }, opts), (v) => {
|
|
473
|
+
const { countries, storefrontPaymentSources, storefrontCustomers, analyticsGeoip } = v;
|
|
474
|
+
return countries && storefrontPaymentSources && storefrontCustomers && analyticsGeoip
|
|
475
|
+
? {
|
|
476
|
+
availableCountries: addEmptyListItem(countries.map((v) => ({ value: v.code, label: v.name }))),
|
|
477
|
+
customer: storefrontCustomers[0],
|
|
478
|
+
paymentMethods: storefrontPaymentSources,
|
|
479
|
+
geoip: analyticsGeoip,
|
|
480
|
+
}
|
|
481
|
+
: undefined;
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
const pageData = createStore(null);
|
|
485
|
+
pageData.on(init.event, (_, v) => v);
|
|
486
|
+
const { availableProvinces, country, province } = createAvailableProvincesLogic(binding, []);
|
|
487
|
+
const setStripeElement = createEvent();
|
|
488
|
+
const stripeElement = restore(setStripeElement, null).reset(init.event);
|
|
489
|
+
const form = createForm({
|
|
490
|
+
name: createStringField("name", "", []),
|
|
491
|
+
address: createStringField("address", "", []),
|
|
492
|
+
city: createStringField("city", "", []),
|
|
493
|
+
zip: createStringField("zip", "", []),
|
|
494
|
+
country,
|
|
495
|
+
province,
|
|
496
|
+
as_default: createBooleanField("as_default", false),
|
|
497
|
+
});
|
|
498
|
+
const formToggleState = createFormToggleState(binding, form);
|
|
499
|
+
formToggleState.isFormVisible.reset(init.event);
|
|
500
|
+
forward({
|
|
501
|
+
from: init.event,
|
|
502
|
+
to: form.reset,
|
|
503
|
+
});
|
|
504
|
+
forward({
|
|
505
|
+
from: init.event.map((v) => {
|
|
506
|
+
const dbid = v.customer.default_billing_address_id;
|
|
507
|
+
const dsid = v.customer.default_shipping_address_id;
|
|
508
|
+
const addrs = v.customer.addresses;
|
|
509
|
+
const addr = addrs.find((a) => a.id === dbid) || addrs.find((a) => a.id === dsid) || addrs.find(() => true);
|
|
510
|
+
if (addr) {
|
|
511
|
+
return {
|
|
512
|
+
name: addr.name,
|
|
513
|
+
address: addr.address1,
|
|
514
|
+
city: addr.city,
|
|
515
|
+
zip: addr.zip,
|
|
516
|
+
country: addr.country?.code || "",
|
|
517
|
+
province: addr.province?.code || "",
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
return {
|
|
522
|
+
name: "",
|
|
523
|
+
address: "",
|
|
524
|
+
city: "",
|
|
525
|
+
zip: "",
|
|
526
|
+
country: v.geoip.country?.code || "",
|
|
527
|
+
province: v.geoip.province?.code || "",
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
}),
|
|
531
|
+
to: form.init,
|
|
532
|
+
});
|
|
533
|
+
const additionalFormSubmitData = combine(stripeElement, binding.internalConfig, (stripeElement, config) => ({
|
|
534
|
+
stripeElement,
|
|
535
|
+
config,
|
|
536
|
+
}));
|
|
537
|
+
const addPaymentMethodFx = createEffect(async (p) => {
|
|
538
|
+
const { shopID, opts } = p.config;
|
|
539
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
540
|
+
if (!p.config.stripePromise)
|
|
541
|
+
return { kind: "custom_error", text: "stripePromise is not defined in config" };
|
|
542
|
+
if (!p.data.stripeElement)
|
|
543
|
+
return { kind: "custom_error", text: "stripeElement is not set" };
|
|
544
|
+
const stripe = await p.config.stripePromise;
|
|
545
|
+
if (!stripe)
|
|
546
|
+
return { kind: "custom_error", text: "failed loading stripe library" };
|
|
547
|
+
const result = await stripe.createPaymentMethod({
|
|
548
|
+
type: "card",
|
|
549
|
+
card: p.data.stripeElement,
|
|
550
|
+
billing_details: p.data.billingDetails,
|
|
551
|
+
});
|
|
552
|
+
if (result.error)
|
|
553
|
+
return {
|
|
554
|
+
kind: "custom_error",
|
|
555
|
+
text: "createPaymentMethod error: " + result.error.message || "\n" + JSON.stringify(result.error, null, 2),
|
|
556
|
+
};
|
|
557
|
+
const payment_method = result.paymentMethod.id;
|
|
558
|
+
const resp = await request(createPaymentSourceMutation)({ shopID, data: { payment_method } }, opts);
|
|
559
|
+
if (resp.kind !== "data")
|
|
560
|
+
return resp;
|
|
561
|
+
const default_payment_source_id = resp.data[0].id;
|
|
562
|
+
if (p.data.asDefault) {
|
|
563
|
+
const resp = await request(modifyCustomerMutation)({ shopID, id: jwt.customer_id, data: { default_payment_source_id } }, opts);
|
|
564
|
+
if (resp.kind !== "data")
|
|
565
|
+
return resp;
|
|
566
|
+
}
|
|
567
|
+
return { kind: "data", data: true };
|
|
568
|
+
});
|
|
569
|
+
const deletePaymentMethodFx = createEffect(async (p) => {
|
|
570
|
+
const { shopID, opts } = p.config;
|
|
571
|
+
return request(deletePaymentSourceMutation)({ shopID, id: p.data }, opts);
|
|
572
|
+
});
|
|
573
|
+
function initStripeField() {
|
|
574
|
+
const setInvalid = createEvent();
|
|
575
|
+
const setComplete = createEvent();
|
|
576
|
+
const setAPIError = createEvent();
|
|
577
|
+
const touched = createStore(false).reset(init.event).reset(form.reset);
|
|
578
|
+
const complete = restore(setComplete, false).reset(init.event).reset(form.reset);
|
|
579
|
+
const invalid = restore(setInvalid, null).reset(init.event).reset(form.reset);
|
|
580
|
+
const apiError = restore(setAPIError, null).reset(init.event).reset(form.reset);
|
|
581
|
+
const error = combine(touched, invalid, complete, apiError, (touched, invalid, complete, apiError) => {
|
|
582
|
+
if (apiError)
|
|
583
|
+
return apiError;
|
|
584
|
+
if (invalid)
|
|
585
|
+
return invalid;
|
|
586
|
+
if (touched && !complete)
|
|
587
|
+
return "incomplete";
|
|
588
|
+
return null;
|
|
589
|
+
});
|
|
590
|
+
return {
|
|
591
|
+
setAPIError,
|
|
592
|
+
setInvalid,
|
|
593
|
+
setComplete,
|
|
594
|
+
touched,
|
|
595
|
+
complete,
|
|
596
|
+
invalid,
|
|
597
|
+
apiError,
|
|
598
|
+
error,
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
const stripeNumber = initStripeField();
|
|
602
|
+
const stripeExpiry = initStripeField();
|
|
603
|
+
const stripeCVC = initStripeField();
|
|
604
|
+
const stripeComplete = combineEvery(stripeNumber.complete, stripeExpiry.complete, stripeCVC.complete);
|
|
605
|
+
forward({
|
|
606
|
+
from: form.submit.map(() => true),
|
|
607
|
+
to: [stripeNumber.touched, stripeExpiry.touched, stripeCVC.touched],
|
|
608
|
+
});
|
|
609
|
+
guard({
|
|
610
|
+
source: sample(additionalFormSubmitData, form.submitted, (adata, data) => ({
|
|
611
|
+
config: adata.config,
|
|
612
|
+
data: {
|
|
613
|
+
billingDetails: formToBillingDetails(data),
|
|
614
|
+
asDefault: data.as_default,
|
|
615
|
+
stripeElement: adata.stripeElement,
|
|
616
|
+
},
|
|
617
|
+
})),
|
|
618
|
+
filter: combine(binding.everythingIdle, stripeComplete, (a, b) => a && b),
|
|
619
|
+
target: addPaymentMethodFx,
|
|
620
|
+
});
|
|
621
|
+
const addPaymentMethodResult = requestResponseSplit(addPaymentMethodFx.doneData);
|
|
622
|
+
// success
|
|
623
|
+
forward({
|
|
624
|
+
from: addPaymentMethodResult.data,
|
|
625
|
+
to: binding.reloadPage,
|
|
626
|
+
});
|
|
627
|
+
// failure
|
|
628
|
+
forward({
|
|
629
|
+
// reset api errors "first"
|
|
630
|
+
from: addPaymentMethodResult.error.map(() => null),
|
|
631
|
+
to: [stripeNumber.setAPIError, stripeExpiry.setAPIError, stripeCVC.setAPIError],
|
|
632
|
+
});
|
|
633
|
+
splitMap(addPaymentMethodResult.error)
|
|
634
|
+
.map(matchNumberErrorFromRR, stripeNumber.setAPIError)
|
|
635
|
+
.map(matchExpiryErrorFromRR, stripeExpiry.setAPIError)
|
|
636
|
+
.map(matchCVCErrorFromRR, stripeCVC.setAPIError)
|
|
637
|
+
.fallback(handleFormFailure({ form, unexpectedError: binding.unexpectedError }));
|
|
638
|
+
const deletePaymentMethodResult = requestResponseSplit(deletePaymentMethodFx.doneData);
|
|
639
|
+
// success
|
|
640
|
+
forward({
|
|
641
|
+
from: deletePaymentMethodResult.data,
|
|
642
|
+
to: binding.reloadPage,
|
|
643
|
+
});
|
|
644
|
+
// failure
|
|
645
|
+
forward({
|
|
646
|
+
from: deletePaymentMethodResult.error,
|
|
647
|
+
to: binding.unexpectedError,
|
|
648
|
+
});
|
|
649
|
+
const deletePaymentMethod = createEvent();
|
|
650
|
+
guard({
|
|
651
|
+
source: sample(binding.internalConfig, deletePaymentMethod, (config, data) => ({ config, data })),
|
|
652
|
+
filter: binding.everythingIdle,
|
|
653
|
+
target: deletePaymentMethodFx,
|
|
654
|
+
});
|
|
655
|
+
return {
|
|
656
|
+
init,
|
|
657
|
+
form,
|
|
658
|
+
...formToggleState,
|
|
659
|
+
pageData,
|
|
660
|
+
availableProvinces: availableProvinces.map((v) => addEmptyListItem(v.map((v) => ({ value: v.code, label: v.name })))),
|
|
661
|
+
somethingIsPending: combineSome(init.pending, addPaymentMethodFx.pending, deletePaymentMethodFx.pending),
|
|
662
|
+
setStripeElement,
|
|
663
|
+
stripeNumber,
|
|
664
|
+
stripeExpiry,
|
|
665
|
+
stripeCVC,
|
|
666
|
+
deletePaymentMethod,
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
//===================================================================================================================
|
|
670
|
+
//===================================================================================================================
|
|
671
|
+
//===================================================================================================================
|
|
672
|
+
function createOrdersPageGraph(binding) {
|
|
673
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
674
|
+
const { shopID, opts } = config;
|
|
675
|
+
return mapResponseData(await request(getOrdersPageQuery)({ shopID, lastKey: "" }, opts), (v) => ({
|
|
676
|
+
orders: v.items,
|
|
677
|
+
lastKey: v.last_key,
|
|
678
|
+
}));
|
|
679
|
+
});
|
|
680
|
+
const getPageFx = createEffect(async (p) => {
|
|
681
|
+
const { shopID, opts } = p.config;
|
|
682
|
+
return request(getOrdersPageQuery)({ shopID, lastKey: p.data }, opts);
|
|
683
|
+
});
|
|
684
|
+
const loadMore = createEvent();
|
|
685
|
+
// init orders and last key stores from API response
|
|
686
|
+
const orders = createStore([]);
|
|
687
|
+
const lastKey = createStore("");
|
|
688
|
+
orders.on(init.event, (_, v) => v.orders);
|
|
689
|
+
lastKey.on(init.event, (_, v) => v.lastKey);
|
|
690
|
+
// on loadMore, sample lastKey and fetch next page (if not already pending)
|
|
691
|
+
guard({
|
|
692
|
+
source: sample(binding.internalConfig, sample(lastKey, loadMore), (config, data) => ({ config, data })),
|
|
693
|
+
filter: binding.everythingIdle,
|
|
694
|
+
target: getPageFx,
|
|
695
|
+
});
|
|
696
|
+
const { data: getPageData, error: getPageError } = requestResponseSplit(getPageFx.doneData);
|
|
697
|
+
// success: propagate new data to stores (note, last key is only applied when it's there)
|
|
698
|
+
orders.on(getPageData.map((v) => v.items), (orders, newOrders) => [...orders, ...newOrders]);
|
|
699
|
+
lastKey.on(getPageData.filterMap((v) => v.last_key || undefined), (_, v) => v);
|
|
700
|
+
// error: report unexpected error
|
|
701
|
+
forward({ from: getPageError, to: binding.unexpectedError });
|
|
702
|
+
return {
|
|
703
|
+
init,
|
|
704
|
+
orders,
|
|
705
|
+
loadMore,
|
|
706
|
+
somethingIsPending: combineSome(init.pending, getPageFx.pending),
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
//===================================================================================================================
|
|
710
|
+
//===================================================================================================================
|
|
711
|
+
//===================================================================================================================
|
|
712
|
+
function createSubscriptionsPageGraph(binding) {
|
|
713
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
714
|
+
const { shopID, opts } = config;
|
|
715
|
+
return mapResponseData(await request(getSubscriptionsPageQuery)({ shopID, lastKey: "" }, opts), (v) => ({
|
|
716
|
+
subscriptions: v.items,
|
|
717
|
+
lastKey: v.last_key,
|
|
718
|
+
}));
|
|
719
|
+
});
|
|
720
|
+
const getPageFx = createEffect(async (p) => {
|
|
721
|
+
const { shopID, opts } = p.config;
|
|
722
|
+
return request(getSubscriptionsPageQuery)({ shopID, lastKey: p.data }, opts);
|
|
723
|
+
});
|
|
724
|
+
const loadMore = createEvent();
|
|
725
|
+
// init subscriptions and last key stores from API response
|
|
726
|
+
const subscriptions = createStore([]);
|
|
727
|
+
const lastKey = createStore("");
|
|
728
|
+
subscriptions.on(init.event, (_, v) => v.subscriptions);
|
|
729
|
+
lastKey.on(init.event, (_, v) => v.lastKey);
|
|
730
|
+
// on loadMore, sample lastKey and fetch next page (if not already pending)
|
|
731
|
+
guard({
|
|
732
|
+
source: sample(binding.internalConfig, sample(lastKey, loadMore), (config, data) => ({ config, data })),
|
|
733
|
+
filter: binding.everythingIdle,
|
|
734
|
+
target: getPageFx,
|
|
735
|
+
});
|
|
736
|
+
const { data: getPageData, error: getPageError } = requestResponseSplit(getPageFx.doneData);
|
|
737
|
+
// success: propagate new data to stores (note, last key is only applied when it's there)
|
|
738
|
+
subscriptions.on(getPageData.map((v) => v.items), (subscriptions, newSubscriptions) => [...subscriptions, ...newSubscriptions]);
|
|
739
|
+
lastKey.on(getPageData.filterMap((v) => v.last_key || undefined), (_, v) => v);
|
|
740
|
+
// error: report unexpected error
|
|
741
|
+
forward({ from: getPageError, to: binding.unexpectedError });
|
|
742
|
+
return {
|
|
743
|
+
init,
|
|
744
|
+
subscriptions,
|
|
745
|
+
loadMore,
|
|
746
|
+
somethingIsPending: combineSome(init.pending, getPageFx.pending),
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
//===================================================================================================================
|
|
750
|
+
//===================================================================================================================
|
|
751
|
+
//===================================================================================================================
|
|
752
|
+
function createReturnsPageGraph(binding) {
|
|
753
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
754
|
+
const { shopID, opts } = config;
|
|
755
|
+
return mapResponseData(await request(getReturnsPageQuery)({ shopID, lastKey: "" }, opts), (v) => ({
|
|
756
|
+
returns: v.items,
|
|
757
|
+
lastKey: v.last_key,
|
|
758
|
+
}));
|
|
759
|
+
});
|
|
760
|
+
const getPageFx = createEffect(async (p) => {
|
|
761
|
+
const { shopID, opts } = p.config;
|
|
762
|
+
return request(getReturnsPageQuery)({ shopID, lastKey: p.data }, opts);
|
|
763
|
+
});
|
|
764
|
+
const loadMore = createEvent();
|
|
765
|
+
// init returns and last key stores from API response
|
|
766
|
+
const returns = createStore([]);
|
|
767
|
+
const lastKey = createStore("");
|
|
768
|
+
returns.on(init.event, (_, v) => v.returns);
|
|
769
|
+
lastKey.on(init.event, (_, v) => v.lastKey);
|
|
770
|
+
// on loadMore, sample lastKey and fetch next page (if not already pending)
|
|
771
|
+
guard({
|
|
772
|
+
source: sample(binding.internalConfig, sample(lastKey, loadMore), (config, data) => ({ config, data })),
|
|
773
|
+
filter: binding.everythingIdle,
|
|
774
|
+
target: getPageFx,
|
|
775
|
+
});
|
|
776
|
+
const { data: getPageData, error: getPageError } = requestResponseSplit(getPageFx.doneData);
|
|
777
|
+
// success: propagate new data to stores (note, last key is only applied when it's there)
|
|
778
|
+
returns.on(getPageData.map((v) => v.items), (returns, newReturns) => [...returns, ...newReturns]);
|
|
779
|
+
lastKey.on(getPageData.filterMap((v) => v.last_key || undefined), (_, v) => v);
|
|
780
|
+
// error: report unexpected error
|
|
781
|
+
forward({ from: getPageError, to: binding.unexpectedError });
|
|
782
|
+
return {
|
|
783
|
+
init,
|
|
784
|
+
returns,
|
|
785
|
+
loadMore,
|
|
786
|
+
somethingIsPending: combineSome(init.pending, getPageFx.pending),
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
//===================================================================================================================
|
|
790
|
+
//===================================================================================================================
|
|
791
|
+
//===================================================================================================================
|
|
792
|
+
function createFavoritesPageGraph(binding) {
|
|
793
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
794
|
+
const { shopID, opts } = config;
|
|
795
|
+
return mapResponseData(await request(getFavoritesQuery)({ shopID }, opts), (v) => ({
|
|
796
|
+
favorites: v.sort((a, b) => a.created_at.localeCompare(b.created_at)),
|
|
797
|
+
}));
|
|
798
|
+
});
|
|
799
|
+
const favorites = createStore([]);
|
|
800
|
+
favorites.on(init.event, (_, v) => v.favorites);
|
|
801
|
+
forward({
|
|
802
|
+
from: init.event.map((v) => compact(v.favorites.map((v) => v.variant
|
|
803
|
+
? {
|
|
804
|
+
id: v.id,
|
|
805
|
+
variantID: v.variant.id,
|
|
806
|
+
inventoryNotification: v.inventory_notification,
|
|
807
|
+
priceNotification: v.price_notification,
|
|
808
|
+
}
|
|
809
|
+
: null))),
|
|
810
|
+
to: binding.setFavorites,
|
|
811
|
+
});
|
|
812
|
+
const addFavoriteFx = createEffect(async (p) => {
|
|
813
|
+
const { shopID, opts } = p.config;
|
|
814
|
+
return request(createFavoriteMutation)({ shopID, data: p.data }, opts);
|
|
815
|
+
});
|
|
816
|
+
const addFavoriteResult = requestResponseSplit(addFavoriteFx.doneData);
|
|
817
|
+
// success
|
|
818
|
+
forward({
|
|
819
|
+
from: addFavoriteResult.data.map(() => "favorites"),
|
|
820
|
+
to: binding.reloadPageIfActive,
|
|
821
|
+
});
|
|
822
|
+
forward({
|
|
823
|
+
from: addFavoriteFx.done.filterMap((v) => v.result.kind === "data"
|
|
824
|
+
? {
|
|
825
|
+
id: v.result.data[0].id,
|
|
826
|
+
variantID: v.params.data.variant_id,
|
|
827
|
+
inventoryNotification: v.result.data[0].inventory_notification,
|
|
828
|
+
priceNotification: v.result.data[0].price_notification,
|
|
829
|
+
}
|
|
830
|
+
: undefined),
|
|
831
|
+
to: binding.addFavoriteToInfo,
|
|
832
|
+
});
|
|
833
|
+
forward({
|
|
834
|
+
from: addFavoriteResult.data.map(() => "favorite_added"),
|
|
835
|
+
to: binding.message,
|
|
836
|
+
});
|
|
837
|
+
// failure
|
|
838
|
+
forward({
|
|
839
|
+
from: addFavoriteResult.error,
|
|
840
|
+
to: binding.unexpectedError,
|
|
841
|
+
});
|
|
842
|
+
const deleteFavoriteFx = createEffect(async (p) => {
|
|
843
|
+
const { shopID, opts } = p.config;
|
|
844
|
+
return request(deleteFavoriteMutation)({ shopID, id: p.data }, opts);
|
|
845
|
+
});
|
|
846
|
+
const deleteFavoriteResult = requestResponseSplit(deleteFavoriteFx.doneData);
|
|
847
|
+
// success
|
|
848
|
+
forward({
|
|
849
|
+
from: deleteFavoriteResult.data.map(() => "favorites"),
|
|
850
|
+
to: binding.reloadPageIfActive,
|
|
851
|
+
});
|
|
852
|
+
forward({
|
|
853
|
+
from: deleteFavoriteFx.done.filterMap((v) => (v.result.kind === "data" ? v.params.data : undefined)),
|
|
854
|
+
to: binding.removeFavoriteFromInfo,
|
|
855
|
+
});
|
|
856
|
+
forward({
|
|
857
|
+
from: deleteFavoriteResult.data.map(() => "favorite_deleted"),
|
|
858
|
+
to: binding.message,
|
|
859
|
+
});
|
|
860
|
+
// failure
|
|
861
|
+
forward({
|
|
862
|
+
from: deleteFavoriteResult.error,
|
|
863
|
+
to: binding.unexpectedError,
|
|
864
|
+
});
|
|
865
|
+
const modifyFavoriteFx = createEffect(async (p) => {
|
|
866
|
+
const { shopID, opts } = p.config;
|
|
867
|
+
return request(modifyFavoriteMutation)({ shopID, id: p.data[0], data: p.data[1] }, opts);
|
|
868
|
+
});
|
|
869
|
+
const modifyFavoriteResult = requestResponseSplit(modifyFavoriteFx.doneData);
|
|
870
|
+
// success
|
|
871
|
+
forward({
|
|
872
|
+
from: modifyFavoriteResult.data.map(() => "favorites"),
|
|
873
|
+
to: binding.reloadPageIfActive,
|
|
874
|
+
});
|
|
875
|
+
forward({
|
|
876
|
+
from: modifyFavoriteFx.done.filterMap((v) => v.result.kind === "data"
|
|
877
|
+
? {
|
|
878
|
+
id: v.result.data[0].id,
|
|
879
|
+
variantID: v.result.data[0].variant?.id || "",
|
|
880
|
+
inventoryNotification: v.result.data[0].inventory_notification,
|
|
881
|
+
priceNotification: v.result.data[0].price_notification,
|
|
882
|
+
}
|
|
883
|
+
: undefined),
|
|
884
|
+
to: binding.modifyFavoriteInInfo,
|
|
885
|
+
});
|
|
886
|
+
forward({
|
|
887
|
+
from: modifyFavoriteResult.data.map(() => "favorite_modified"),
|
|
888
|
+
to: binding.message,
|
|
889
|
+
});
|
|
890
|
+
// failure
|
|
891
|
+
forward({
|
|
892
|
+
from: modifyFavoriteResult.error,
|
|
893
|
+
to: binding.unexpectedError,
|
|
894
|
+
});
|
|
895
|
+
const deleteFavorite = createEvent();
|
|
896
|
+
guard({
|
|
897
|
+
source: sample(binding.internalConfig, deleteFavorite, (config, data) => ({ config, data })),
|
|
898
|
+
filter: binding.everythingIdle,
|
|
899
|
+
target: deleteFavoriteFx,
|
|
900
|
+
});
|
|
901
|
+
const addFavorite = createEvent();
|
|
902
|
+
const addFavoriteEx = createEvent();
|
|
903
|
+
guard({
|
|
904
|
+
source: sample(binding.internalConfig, addFavorite, (config, variant_id) => ({
|
|
905
|
+
config,
|
|
906
|
+
data: { variant_id },
|
|
907
|
+
})),
|
|
908
|
+
filter: binding.everythingIdle,
|
|
909
|
+
target: addFavoriteFx,
|
|
910
|
+
});
|
|
911
|
+
guard({
|
|
912
|
+
source: sample(binding.internalConfig, addFavoriteEx, (config, data) => ({ config, data })),
|
|
913
|
+
filter: binding.everythingIdle,
|
|
914
|
+
target: addFavoriteFx,
|
|
915
|
+
});
|
|
916
|
+
const modifyFavorite = createEvent();
|
|
917
|
+
guard({
|
|
918
|
+
source: sample(binding.internalConfig, modifyFavorite, (config, data) => ({ config, data })),
|
|
919
|
+
filter: binding.everythingIdle,
|
|
920
|
+
target: modifyFavoriteFx,
|
|
921
|
+
});
|
|
922
|
+
return {
|
|
923
|
+
init,
|
|
924
|
+
favorites,
|
|
925
|
+
addFavorite,
|
|
926
|
+
addFavoriteEx,
|
|
927
|
+
modifyFavorite,
|
|
928
|
+
deleteFavorite,
|
|
929
|
+
somethingIsPending: combineSome(init.pending, addFavoriteFx.pending, modifyFavoriteFx.pending, deleteFavoriteFx.pending),
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
//===================================================================================================================
|
|
933
|
+
//===================================================================================================================
|
|
934
|
+
//===================================================================================================================
|
|
935
|
+
function addressToAPI(addr) {
|
|
936
|
+
const { country, province, latitude, longitude, ...apiAddr } = addr;
|
|
937
|
+
return {
|
|
938
|
+
...apiAddr,
|
|
939
|
+
country: addr.country ? addr.country.code : "",
|
|
940
|
+
province: addr.province ? addr.province.code : "",
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
function createAddressesPageGraph(binding) {
|
|
944
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
945
|
+
const { shopID, opts } = config;
|
|
946
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
947
|
+
return multiResponseToResponse(await requestMulti(getCustomerAddressesPageDataQuery)({ shopID, customerID: jwt.customer_id }, opts), (v) => {
|
|
948
|
+
const { analyticsGeoip, countries, storefrontCustomers } = v;
|
|
949
|
+
if (!analyticsGeoip || !countries || !storefrontCustomers) {
|
|
950
|
+
return undefined;
|
|
951
|
+
}
|
|
952
|
+
let geoCountryCode = analyticsGeoip.country?.code || "";
|
|
953
|
+
let geoProvinceCode = analyticsGeoip.province?.code || "";
|
|
954
|
+
if (!countries.find((v) => v.code === geoCountryCode)) {
|
|
955
|
+
geoCountryCode = "";
|
|
956
|
+
geoProvinceCode = "";
|
|
957
|
+
}
|
|
958
|
+
return {
|
|
959
|
+
availableCountries: addEmptyListItem(countries.map((v) => ({ value: v.code, label: v.name }))),
|
|
960
|
+
customer: storefrontCustomers[0],
|
|
961
|
+
geoCountryCode,
|
|
962
|
+
geoProvinceCode,
|
|
963
|
+
};
|
|
964
|
+
});
|
|
965
|
+
});
|
|
966
|
+
const { availableProvinces, country, province } = createAvailableProvincesLogic(binding, [validNonEmpty]);
|
|
967
|
+
const form = createForm({
|
|
968
|
+
id: createStringField("id", "", []),
|
|
969
|
+
name: createStringField("name", "", [validNonEmpty, validMaxLength160]),
|
|
970
|
+
address1: createStringField("address1", "", [validNonEmpty, validMaxLength190]),
|
|
971
|
+
address2: createStringField("address2", "", [validMaxLength190]),
|
|
972
|
+
city: createStringField("city", "", [validNonEmpty, validMaxLength80]),
|
|
973
|
+
zip: createStringField("zip", "", [validNonEmpty, validMaxLength32]),
|
|
974
|
+
country,
|
|
975
|
+
province,
|
|
976
|
+
default_shipping: createBooleanField("default_shipping", false),
|
|
977
|
+
default_billing: createBooleanField("default_billing", false),
|
|
978
|
+
});
|
|
979
|
+
// prefill country/province with geoip data
|
|
980
|
+
forward({
|
|
981
|
+
from: init.event.map((v) => v.geoCountryCode),
|
|
982
|
+
to: form.country.setInitialValue,
|
|
983
|
+
});
|
|
984
|
+
forward({
|
|
985
|
+
from: init.event.map((v) => v.geoProvinceCode),
|
|
986
|
+
to: form.province.setInitialValue,
|
|
987
|
+
});
|
|
988
|
+
const modifyCustomerFx = createEffect(async (p) => {
|
|
989
|
+
const { shopID, opts } = p.config;
|
|
990
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
991
|
+
return request(modifyCustomerMutation)({ shopID, id: jwt.customer_id, data: p.data }, opts);
|
|
992
|
+
});
|
|
993
|
+
const modifyCustomerResult = requestResponseSplitFirst(modifyCustomerFx.doneData);
|
|
994
|
+
// success
|
|
995
|
+
forward({
|
|
996
|
+
from: modifyCustomerResult.data,
|
|
997
|
+
to: binding.reloadPage,
|
|
998
|
+
});
|
|
999
|
+
// failure
|
|
1000
|
+
handleFormFailure({ source: modifyCustomerResult.error, form, unexpectedError: binding.unexpectedError });
|
|
1001
|
+
const pageData = createStore(null);
|
|
1002
|
+
pageData.on(init.event, (_, v) => v);
|
|
1003
|
+
// show form for a particular address
|
|
1004
|
+
const isFormVisible = createStore(false);
|
|
1005
|
+
const addressEditIndex = createStore(-1);
|
|
1006
|
+
const showFormFor = createEvent();
|
|
1007
|
+
const toggleFormVisibility = createEvent();
|
|
1008
|
+
const formVisibilityChanged = createEvent();
|
|
1009
|
+
guard({
|
|
1010
|
+
source: showFormFor.map((index) => ({ visible: true, index })),
|
|
1011
|
+
filter: binding.everythingIdle,
|
|
1012
|
+
target: formVisibilityChanged,
|
|
1013
|
+
});
|
|
1014
|
+
guard({
|
|
1015
|
+
source: sample(isFormVisible, toggleFormVisibility, (v) => ({ visible: !v, index: -1 })),
|
|
1016
|
+
filter: binding.everythingIdle,
|
|
1017
|
+
target: formVisibilityChanged,
|
|
1018
|
+
});
|
|
1019
|
+
forward({
|
|
1020
|
+
from: sample(addressEditIndex, init.event, (index) => ({ visible: false, index })),
|
|
1021
|
+
to: formVisibilityChanged,
|
|
1022
|
+
});
|
|
1023
|
+
forward({
|
|
1024
|
+
from: formVisibilityChanged.map((v) => v.visible),
|
|
1025
|
+
to: isFormVisible,
|
|
1026
|
+
});
|
|
1027
|
+
forward({
|
|
1028
|
+
from: formVisibilityChanged.filterMap((v) => (v.visible ? v.index : undefined)),
|
|
1029
|
+
to: addressEditIndex,
|
|
1030
|
+
});
|
|
1031
|
+
forward({
|
|
1032
|
+
from: sample(pageData, formVisibilityChanged.filterMap((v) => (v.visible ? v : undefined)), (pageData, { index }) => {
|
|
1033
|
+
const empty = {
|
|
1034
|
+
id: "",
|
|
1035
|
+
name: "",
|
|
1036
|
+
address1: "",
|
|
1037
|
+
address2: "",
|
|
1038
|
+
city: "",
|
|
1039
|
+
zip: "",
|
|
1040
|
+
country: "",
|
|
1041
|
+
province: "",
|
|
1042
|
+
default_shipping: false,
|
|
1043
|
+
default_billing: false,
|
|
1044
|
+
};
|
|
1045
|
+
if (index === -1)
|
|
1046
|
+
return empty;
|
|
1047
|
+
const c = pageData?.customer;
|
|
1048
|
+
if (!c)
|
|
1049
|
+
return empty;
|
|
1050
|
+
const a = c.addresses[index];
|
|
1051
|
+
if (!a)
|
|
1052
|
+
return empty;
|
|
1053
|
+
return {
|
|
1054
|
+
id: a.id,
|
|
1055
|
+
name: a.name,
|
|
1056
|
+
address1: a.address1,
|
|
1057
|
+
address2: a.address2,
|
|
1058
|
+
city: a.city,
|
|
1059
|
+
zip: a.zip,
|
|
1060
|
+
country: a.country?.code || "",
|
|
1061
|
+
province: a.province?.code || "",
|
|
1062
|
+
default_shipping: a.id === c.default_shipping_address_id,
|
|
1063
|
+
default_billing: a.id === c.default_billing_address_id,
|
|
1064
|
+
};
|
|
1065
|
+
}),
|
|
1066
|
+
to: form.init,
|
|
1067
|
+
});
|
|
1068
|
+
const formSubmit = sample(combine({ pageData, addressEditIndex }), form.submitted, ({ pageData, addressEditIndex }, data) => {
|
|
1069
|
+
if (addressEditIndex === -1) {
|
|
1070
|
+
const addresses = pageData?.customer.addresses || [];
|
|
1071
|
+
const { default_billing, default_shipping, ...apiData } = data;
|
|
1072
|
+
return {
|
|
1073
|
+
addresses: [
|
|
1074
|
+
...addresses.map(addressToAPI),
|
|
1075
|
+
{
|
|
1076
|
+
...apiData,
|
|
1077
|
+
phone: "",
|
|
1078
|
+
company: "",
|
|
1079
|
+
},
|
|
1080
|
+
],
|
|
1081
|
+
default_billing_address_id: default_billing ? "first" : undefined,
|
|
1082
|
+
default_shipping_address_id: default_shipping ? "first" : undefined,
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
else {
|
|
1086
|
+
const { default_billing, default_shipping, ...apiData } = data;
|
|
1087
|
+
const addresses = [...(pageData?.customer.addresses || [])].map(addressToAPI);
|
|
1088
|
+
addresses[addressEditIndex] = { ...apiData, phone: "", company: "" };
|
|
1089
|
+
const prevDB = pageData?.customer.default_billing_address_id === apiData.id;
|
|
1090
|
+
const prevDS = pageData?.customer.default_shipping_address_id === apiData.id;
|
|
1091
|
+
return {
|
|
1092
|
+
addresses,
|
|
1093
|
+
default_billing_address_id: default_billing !== prevDB ? (default_billing ? apiData.id : "") : undefined,
|
|
1094
|
+
default_shipping_address_id: default_shipping !== prevDS ? (default_shipping ? apiData.id : "") : undefined,
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1098
|
+
guard({
|
|
1099
|
+
source: sample(binding.internalConfig, formSubmit, (config, data) => ({ config, data })),
|
|
1100
|
+
filter: binding.everythingIdle,
|
|
1101
|
+
target: modifyCustomerFx,
|
|
1102
|
+
});
|
|
1103
|
+
const deleteAddress = createEvent();
|
|
1104
|
+
const deleteAddressValid = sample(pageData, deleteAddress, (pageData, idx) => {
|
|
1105
|
+
const addressesLength = pageData?.customer.addresses.length || 0;
|
|
1106
|
+
return idx >= 0 && idx < addressesLength ? idx : undefined;
|
|
1107
|
+
}).filterMap((v) => v);
|
|
1108
|
+
const deleteAddressSubmit = sample(pageData, deleteAddressValid, (pageData, idx) => {
|
|
1109
|
+
const dbid = pageData?.customer.default_billing_address_id || "";
|
|
1110
|
+
const dsid = pageData?.customer.default_shipping_address_id || "";
|
|
1111
|
+
const addresses = pageData?.customer.addresses.filter((_, aidx) => aidx !== idx).map(addressToAPI);
|
|
1112
|
+
return {
|
|
1113
|
+
addresses,
|
|
1114
|
+
default_billing_address_id: addresses?.some((a) => a.id === dbid) ? dbid : "",
|
|
1115
|
+
default_shipping_address_id: addresses?.some((a) => a.id === dsid) ? dsid : "",
|
|
1116
|
+
};
|
|
1117
|
+
});
|
|
1118
|
+
const makeDefault = createEvent();
|
|
1119
|
+
const makeDefaultValid = sample(pageData, makeDefault, (pageData, idx) => {
|
|
1120
|
+
const addresses = pageData?.customer.addresses;
|
|
1121
|
+
return addresses && idx >= 0 && idx < addresses.length ? addresses[idx].id : undefined;
|
|
1122
|
+
}).filterMap((v) => v);
|
|
1123
|
+
const makeDefaultSubmit = makeDefaultValid.map((id) => {
|
|
1124
|
+
return {
|
|
1125
|
+
default_billing_address_id: id,
|
|
1126
|
+
default_shipping_address_id: id,
|
|
1127
|
+
};
|
|
1128
|
+
});
|
|
1129
|
+
guard({
|
|
1130
|
+
source: sample(binding.internalConfig, deleteAddressSubmit, (config, data) => ({ config, data })),
|
|
1131
|
+
filter: binding.everythingIdle,
|
|
1132
|
+
target: modifyCustomerFx,
|
|
1133
|
+
});
|
|
1134
|
+
guard({
|
|
1135
|
+
source: sample(binding.internalConfig, makeDefaultSubmit, (config, data) => ({ config, data })),
|
|
1136
|
+
filter: binding.everythingIdle,
|
|
1137
|
+
target: modifyCustomerFx,
|
|
1138
|
+
});
|
|
1139
|
+
return {
|
|
1140
|
+
init,
|
|
1141
|
+
form,
|
|
1142
|
+
showFormFor,
|
|
1143
|
+
toggleFormVisibility,
|
|
1144
|
+
isFormVisible,
|
|
1145
|
+
addressEditIndex,
|
|
1146
|
+
pageData,
|
|
1147
|
+
availableProvinces: availableProvinces.map((v) => addEmptyListItem(v.map((v) => ({ value: v.code, label: v.name })))),
|
|
1148
|
+
deleteAddress,
|
|
1149
|
+
makeDefault,
|
|
1150
|
+
somethingIsPending: combineSome(init.pending, modifyCustomerFx.pending),
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
//===================================================================================================================
|
|
1154
|
+
//===================================================================================================================
|
|
1155
|
+
//===================================================================================================================
|
|
1156
|
+
function createOrderPageGraph(binding) {
|
|
1157
|
+
const init = defineInit(binding, async (config, p) => {
|
|
1158
|
+
const { shopID, opts } = config;
|
|
1159
|
+
return mapResponseData(await request(getOrderQuery)({ shopID, id: p.param.orderID }, opts), (v) => ({
|
|
1160
|
+
order: v[0],
|
|
1161
|
+
}));
|
|
1162
|
+
});
|
|
1163
|
+
const order = createStore(null).on(init.event, (_, v) => v.order);
|
|
1164
|
+
const cancelOrderFx = createEffect(async (p) => {
|
|
1165
|
+
const { shopID, opts } = p.config;
|
|
1166
|
+
return request(cancelOrderMutation)({ shopID, id: p.data }, opts);
|
|
1167
|
+
});
|
|
1168
|
+
const cancelOrderResult = requestResponseSplit(cancelOrderFx.doneData);
|
|
1169
|
+
// success
|
|
1170
|
+
forward({
|
|
1171
|
+
from: cancelOrderResult.data,
|
|
1172
|
+
to: binding.reloadPage,
|
|
1173
|
+
});
|
|
1174
|
+
// failure
|
|
1175
|
+
forward({
|
|
1176
|
+
from: cancelOrderResult.error,
|
|
1177
|
+
to: binding.unexpectedError,
|
|
1178
|
+
});
|
|
1179
|
+
const cancelOrder = createEvent();
|
|
1180
|
+
const canCancelOrder = order.map((o) => o !== null && o.on_hold && !o.canceled_at);
|
|
1181
|
+
guard({
|
|
1182
|
+
source: sample(combine({ config: binding.internalConfig, order }), cancelOrder, ({ config, order }) => ({
|
|
1183
|
+
config,
|
|
1184
|
+
data: order?.id || "",
|
|
1185
|
+
})),
|
|
1186
|
+
filter: combineEvery(binding.everythingIdle, canCancelOrder),
|
|
1187
|
+
target: cancelOrderFx,
|
|
1188
|
+
});
|
|
1189
|
+
return {
|
|
1190
|
+
init,
|
|
1191
|
+
order,
|
|
1192
|
+
cancelOrder,
|
|
1193
|
+
canCancelOrder,
|
|
1194
|
+
somethingIsPending: combineSome(init.pending, cancelOrderFx.pending),
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
//===================================================================================================================
|
|
1198
|
+
//===================================================================================================================
|
|
1199
|
+
//===================================================================================================================
|
|
1200
|
+
function createSubscriptionPageGraph(binding) {
|
|
1201
|
+
const init = defineInit(binding, async (config, p) => {
|
|
1202
|
+
const { shopID, opts } = config;
|
|
1203
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
1204
|
+
return multiResponseToResponse(await requestMulti(getSubscriptionQuery)({ shopID, subscriptionID: p.param.subscriptionID, customerID: jwt.customer_id }, opts), (v) => {
|
|
1205
|
+
if (!v.storefrontSubscriptions || !v.storefrontCustomers)
|
|
1206
|
+
return undefined;
|
|
1207
|
+
return {
|
|
1208
|
+
customer: v.storefrontCustomers?.[0],
|
|
1209
|
+
paymentMethods: v.storefrontPaymentSources || [],
|
|
1210
|
+
subscription: v.storefrontSubscriptions[0],
|
|
1211
|
+
};
|
|
1212
|
+
}, true);
|
|
1213
|
+
});
|
|
1214
|
+
const subscription = createStore(null).on(init.event, (_, v) => v.subscription);
|
|
1215
|
+
const customer = createStore(null).on(init.event, (_, v) => v.customer);
|
|
1216
|
+
const paymentMethods = createStore([]).on(init.event, (_, v) => v.paymentMethods);
|
|
1217
|
+
const form = createForm({
|
|
1218
|
+
billing_address: createEnumField("billing_address", "origin_order", []),
|
|
1219
|
+
billing_address_id: createStringField("billing_address_id", "", []),
|
|
1220
|
+
shipping_address: createEnumField("shipping_address", "origin_order", []),
|
|
1221
|
+
shipping_address_id: createStringField("shipping_address_id", "", []),
|
|
1222
|
+
payment_source: createEnumField("payment_source", "origin_order", []),
|
|
1223
|
+
payment_source_id: createStringField("payment_source_id", "", []),
|
|
1224
|
+
});
|
|
1225
|
+
forward({
|
|
1226
|
+
from: init.event.map((v) => {
|
|
1227
|
+
const s = v.subscription;
|
|
1228
|
+
return {
|
|
1229
|
+
billing_address: s?.billing_address || "origin_order",
|
|
1230
|
+
billing_address_id: s?.billing_address_id || "",
|
|
1231
|
+
shipping_address: s?.shipping_address || "origin_order",
|
|
1232
|
+
shipping_address_id: s?.shipping_address_id || "",
|
|
1233
|
+
payment_source: s?.payment_source || "origin_order",
|
|
1234
|
+
payment_source_id: s?.payment_source_id || "",
|
|
1235
|
+
};
|
|
1236
|
+
}),
|
|
1237
|
+
to: form.init,
|
|
1238
|
+
});
|
|
1239
|
+
const cancel = createEvent();
|
|
1240
|
+
const pause = createEvent();
|
|
1241
|
+
const resume = createEvent();
|
|
1242
|
+
const skipNext = createEvent();
|
|
1243
|
+
const editFx = createEffect(async (p) => {
|
|
1244
|
+
const { shopID, opts } = p.config;
|
|
1245
|
+
return request(editSubscriptionMutation)({ shopID, subscriptionID: p.data[0], data: p.data[1] }, opts);
|
|
1246
|
+
});
|
|
1247
|
+
const cancelFx = createEffect(async (p) => {
|
|
1248
|
+
const { shopID, opts } = p.config;
|
|
1249
|
+
return request(cancelSubscriptionMutation)({ shopID, subscriptionID: p.data }, opts);
|
|
1250
|
+
});
|
|
1251
|
+
const pauseFx = createEffect(async (p) => {
|
|
1252
|
+
const { shopID, opts } = p.config;
|
|
1253
|
+
return request(pauseSubscriptionMutation)({ shopID, subscriptionID: p.data }, opts);
|
|
1254
|
+
});
|
|
1255
|
+
const resumeFx = createEffect(async (p) => {
|
|
1256
|
+
const { shopID, opts } = p.config;
|
|
1257
|
+
return request(resumeSubscriptionMutation)({ shopID, subscriptionID: p.data }, opts);
|
|
1258
|
+
});
|
|
1259
|
+
const skipNextFx = createEffect(async (p) => {
|
|
1260
|
+
const { shopID, opts } = p.config;
|
|
1261
|
+
return request(skipNextSubscriptionMutation)({ shopID, subscriptionID: p.data }, opts);
|
|
1262
|
+
});
|
|
1263
|
+
const configAndSubscription = combine({ config: binding.internalConfig, subscription });
|
|
1264
|
+
const connectEventToFx = (ev, fx) => {
|
|
1265
|
+
guard({
|
|
1266
|
+
source: sample(configAndSubscription, ev, (cas) => ({
|
|
1267
|
+
config: cas.config,
|
|
1268
|
+
data: cas.subscription?.id || "",
|
|
1269
|
+
})),
|
|
1270
|
+
filter: binding.everythingIdle,
|
|
1271
|
+
target: fx,
|
|
1272
|
+
});
|
|
1273
|
+
};
|
|
1274
|
+
connectEventToFx(cancel, cancelFx);
|
|
1275
|
+
connectEventToFx(pause, pauseFx);
|
|
1276
|
+
connectEventToFx(resume, resumeFx);
|
|
1277
|
+
connectEventToFx(skipNext, skipNextFx);
|
|
1278
|
+
const cancelResult = requestResponseSplit(cancelFx.doneData);
|
|
1279
|
+
const pauseResult = requestResponseSplit(pauseFx.doneData);
|
|
1280
|
+
const resumeResult = requestResponseSplit(resumeFx.doneData);
|
|
1281
|
+
const skipNextResult = requestResponseSplit(skipNextFx.doneData);
|
|
1282
|
+
// success
|
|
1283
|
+
forward({ from: cancelResult.data, to: binding.reloadPage });
|
|
1284
|
+
forward({ from: pauseResult.data, to: binding.reloadPage });
|
|
1285
|
+
forward({ from: resumeResult.data, to: binding.reloadPage });
|
|
1286
|
+
forward({ from: skipNextResult.data, to: binding.reloadPage });
|
|
1287
|
+
// failure
|
|
1288
|
+
forward({ from: cancelResult.error, to: binding.unexpectedError });
|
|
1289
|
+
forward({ from: pauseResult.error, to: binding.unexpectedError });
|
|
1290
|
+
forward({ from: resumeResult.error, to: binding.unexpectedError });
|
|
1291
|
+
forward({ from: skipNextResult.error, to: binding.unexpectedError });
|
|
1292
|
+
const editResult = requestResponseSplit(editFx.doneData);
|
|
1293
|
+
// success
|
|
1294
|
+
forward({
|
|
1295
|
+
from: editResult.data,
|
|
1296
|
+
to: binding.reloadPage,
|
|
1297
|
+
});
|
|
1298
|
+
// failure
|
|
1299
|
+
handleFormFailure({ source: editResult.error, form, unexpectedError: binding.unexpectedError });
|
|
1300
|
+
const formSubmit = sample(subscription, form.submitted, (subscription, data) => {
|
|
1301
|
+
const r = [subscription?.id || "", data];
|
|
1302
|
+
return r;
|
|
1303
|
+
});
|
|
1304
|
+
guard({
|
|
1305
|
+
source: sample(binding.internalConfig, formSubmit, (config, data) => ({ config, data })),
|
|
1306
|
+
filter: binding.everythingIdle,
|
|
1307
|
+
target: editFx,
|
|
1308
|
+
});
|
|
1309
|
+
const setBillingAddressValueAndID = createEvent();
|
|
1310
|
+
const setShippingAddressValueAndID = createEvent();
|
|
1311
|
+
const setPaymentSourceValueAndID = createEvent();
|
|
1312
|
+
forward({ from: setBillingAddressValueAndID.map((v) => v[0]), to: form.billing_address.change });
|
|
1313
|
+
forward({ from: setBillingAddressValueAndID.map((v) => v[1]), to: form.billing_address_id.change });
|
|
1314
|
+
forward({ from: setShippingAddressValueAndID.map((v) => v[0]), to: form.shipping_address.change });
|
|
1315
|
+
forward({ from: setShippingAddressValueAndID.map((v) => v[1]), to: form.shipping_address_id.change });
|
|
1316
|
+
forward({ from: setPaymentSourceValueAndID.map((v) => v[0]), to: form.payment_source.change });
|
|
1317
|
+
forward({ from: setPaymentSourceValueAndID.map((v) => v[1]), to: form.payment_source_id.change });
|
|
1318
|
+
return {
|
|
1319
|
+
init,
|
|
1320
|
+
form,
|
|
1321
|
+
subscription,
|
|
1322
|
+
customer,
|
|
1323
|
+
paymentMethods,
|
|
1324
|
+
cancel,
|
|
1325
|
+
pause,
|
|
1326
|
+
resume,
|
|
1327
|
+
skipNext,
|
|
1328
|
+
somethingIsPending: combineSome(init.pending, editFx.pending, cancelFx.pending, pauseFx.pending, resumeFx.pending, skipNextFx.pending),
|
|
1329
|
+
setBillingAddressValueAndID,
|
|
1330
|
+
setShippingAddressValueAndID,
|
|
1331
|
+
setPaymentSourceValueAndID,
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
//===================================================================================================================
|
|
1335
|
+
//===================================================================================================================
|
|
1336
|
+
//===================================================================================================================
|
|
1337
|
+
function createReturnPageGraph(binding) {
|
|
1338
|
+
const init = defineInit(binding, async (config, p) => {
|
|
1339
|
+
const { shopID, opts } = config;
|
|
1340
|
+
return multiResponseToResponse(await requestMulti(getReturnQuery)({ shopID, id: p.param.returnID }, opts), (v) => {
|
|
1341
|
+
const { returnReasons: reasons, storefrontReturns } = v;
|
|
1342
|
+
return storefrontReturns
|
|
1343
|
+
? {
|
|
1344
|
+
reasons: reasons || [],
|
|
1345
|
+
ret: storefrontReturns[0],
|
|
1346
|
+
}
|
|
1347
|
+
: undefined;
|
|
1348
|
+
});
|
|
1349
|
+
});
|
|
1350
|
+
const data = createStore(null).on(init.event, (_, v) => v);
|
|
1351
|
+
return {
|
|
1352
|
+
init,
|
|
1353
|
+
data,
|
|
1354
|
+
somethingIsPending: init.pending,
|
|
1355
|
+
};
|
|
1356
|
+
}
|
|
1357
|
+
function createCreateReturnPageGraph(binding) {
|
|
1358
|
+
const init = defineInit(binding, async (config, p) => {
|
|
1359
|
+
const { shopID, opts } = config;
|
|
1360
|
+
return multiResponseToResponse(await requestMulti(getReturnCreationInfoQuery)({ shopID, id: p.param.orderID }, opts), (v) => {
|
|
1361
|
+
const { storefrontOrderFulfillments: fulfillments, storefrontOrders: orders, storefrontReturnsFindPolicy: policy, returnReasons: reasons, } = v;
|
|
1362
|
+
return fulfillments && orders
|
|
1363
|
+
? {
|
|
1364
|
+
fulfillments,
|
|
1365
|
+
order: orders[0],
|
|
1366
|
+
policy: policy || null,
|
|
1367
|
+
reasons: reasons || [],
|
|
1368
|
+
}
|
|
1369
|
+
: undefined;
|
|
1370
|
+
}, true);
|
|
1371
|
+
});
|
|
1372
|
+
const ret = createStore(null);
|
|
1373
|
+
ret.on(init.event, () => null);
|
|
1374
|
+
const refundToCustomerBalance = createStore(false);
|
|
1375
|
+
refundToCustomerBalance.on(init.event, (ov, v) => {
|
|
1376
|
+
const p = v.policy;
|
|
1377
|
+
if (!p)
|
|
1378
|
+
return ov;
|
|
1379
|
+
if (p.refund_option === "customer_balance")
|
|
1380
|
+
return true;
|
|
1381
|
+
return false;
|
|
1382
|
+
});
|
|
1383
|
+
const setRefundToCustomerBalance = createEvent();
|
|
1384
|
+
refundToCustomerBalance.on(setRefundToCustomerBalance, (_, v) => v);
|
|
1385
|
+
const shippingOptionIndex = createStore(0);
|
|
1386
|
+
shippingOptionIndex.reset(init.event);
|
|
1387
|
+
const info = createStore(null);
|
|
1388
|
+
info.on(init.event, (_, v) => v);
|
|
1389
|
+
const setShippingOptionIndex = createEvent();
|
|
1390
|
+
shippingOptionIndex.on(sample(info, setShippingOptionIndex, (info, idx) => {
|
|
1391
|
+
const p = info?.policy;
|
|
1392
|
+
if (!p)
|
|
1393
|
+
return undefined;
|
|
1394
|
+
return Math.max(0, Math.min(idx, p.shipping_options.length - 1));
|
|
1395
|
+
}), (_, v) => v);
|
|
1396
|
+
const items = createStore([]);
|
|
1397
|
+
items.on(init.event, (_, v) => {
|
|
1398
|
+
const vmap = createVariantMap(v.order);
|
|
1399
|
+
return v.fulfillments.map((f) => f.line_items.map((fli) => {
|
|
1400
|
+
const v = vmap[fli.variant_id];
|
|
1401
|
+
const p = v?.product;
|
|
1402
|
+
const quantity = Math.max(0, p?.return_mode === "not_allowed" ? 0 : fli.quantity - fli.returned);
|
|
1403
|
+
return {
|
|
1404
|
+
selected: false,
|
|
1405
|
+
quantity,
|
|
1406
|
+
maxQuantity: quantity,
|
|
1407
|
+
reason: null,
|
|
1408
|
+
};
|
|
1409
|
+
}));
|
|
1410
|
+
});
|
|
1411
|
+
const updateItem = createEvent();
|
|
1412
|
+
items.on(updateItem, (old, [i, j, v]) => {
|
|
1413
|
+
const newItem = { ...old[i][j] };
|
|
1414
|
+
if (v.selected !== undefined)
|
|
1415
|
+
newItem.selected = v.selected;
|
|
1416
|
+
if (v.quantity !== undefined) {
|
|
1417
|
+
newItem.quantity = Math.max(0, Math.min(v.quantity, newItem.maxQuantity));
|
|
1418
|
+
}
|
|
1419
|
+
if (v.reason !== undefined)
|
|
1420
|
+
newItem.reason = v.reason;
|
|
1421
|
+
const newItems = [...old];
|
|
1422
|
+
newItems[i] = [...old[i]];
|
|
1423
|
+
newItems[i][j] = newItem;
|
|
1424
|
+
return newItems;
|
|
1425
|
+
});
|
|
1426
|
+
const submit = createEvent();
|
|
1427
|
+
const createReturnFx = createEffect(async (p) => {
|
|
1428
|
+
const { shopID, opts } = p.config;
|
|
1429
|
+
return request(createReturnMutation)({ shopID, data: p.data }, opts);
|
|
1430
|
+
});
|
|
1431
|
+
const preparedData = combine({ config: binding.internalConfig, items, info, refundToCustomerBalance, shippingOptionIndex }, ({ config, items, info, refundToCustomerBalance, shippingOptionIndex }) => {
|
|
1432
|
+
if (!info || !info.policy)
|
|
1433
|
+
return null;
|
|
1434
|
+
const lineItems = [];
|
|
1435
|
+
info.fulfillments.forEach((f, i) => {
|
|
1436
|
+
f.line_items.forEach((fli, j) => {
|
|
1437
|
+
const item = items[i][j];
|
|
1438
|
+
if (!item.selected)
|
|
1439
|
+
return;
|
|
1440
|
+
if (item.quantity <= 0)
|
|
1441
|
+
return;
|
|
1442
|
+
lineItems.push({
|
|
1443
|
+
fulfillment_id: f.id,
|
|
1444
|
+
line_item_id: fli.line_item_id,
|
|
1445
|
+
reason: item.reason || "other_reason",
|
|
1446
|
+
return_quantity: item.quantity,
|
|
1447
|
+
variant_id: fli.variant_id,
|
|
1448
|
+
});
|
|
1449
|
+
});
|
|
1450
|
+
});
|
|
1451
|
+
if (lineItems.length === 0)
|
|
1452
|
+
return null;
|
|
1453
|
+
const data = {
|
|
1454
|
+
order_id: info.order.id,
|
|
1455
|
+
return_policy_id: info.policy.id,
|
|
1456
|
+
shipping_option_index: shippingOptionIndex,
|
|
1457
|
+
customer_balance: refundToCustomerBalance,
|
|
1458
|
+
line_items: lineItems,
|
|
1459
|
+
};
|
|
1460
|
+
return { config, data };
|
|
1461
|
+
});
|
|
1462
|
+
const canSubmit = preparedData.map((v) => !!v);
|
|
1463
|
+
const submitted = sample(preparedData, submit).filterMap((v) => v || undefined);
|
|
1464
|
+
guard({
|
|
1465
|
+
source: submitted,
|
|
1466
|
+
filter: binding.everythingIdle,
|
|
1467
|
+
target: createReturnFx,
|
|
1468
|
+
});
|
|
1469
|
+
const createReturnResult = requestResponseSplitFirst(createReturnFx.doneData);
|
|
1470
|
+
// success
|
|
1471
|
+
forward({
|
|
1472
|
+
from: createReturnResult.data,
|
|
1473
|
+
to: ret,
|
|
1474
|
+
});
|
|
1475
|
+
// failure
|
|
1476
|
+
forward({
|
|
1477
|
+
from: createReturnResult.error,
|
|
1478
|
+
to: binding.unexpectedError,
|
|
1479
|
+
});
|
|
1480
|
+
return {
|
|
1481
|
+
init,
|
|
1482
|
+
ret,
|
|
1483
|
+
info,
|
|
1484
|
+
items,
|
|
1485
|
+
updateItem,
|
|
1486
|
+
setRefundToCustomerBalance,
|
|
1487
|
+
refundToCustomerBalance,
|
|
1488
|
+
setShippingOptionIndex,
|
|
1489
|
+
shippingOptionIndex,
|
|
1490
|
+
submit,
|
|
1491
|
+
canSubmit,
|
|
1492
|
+
somethingIsPending: combineSome(init.pending, createReturnFx.pending),
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
//===================================================================================================================
|
|
1496
|
+
//===================================================================================================================
|
|
1497
|
+
//===================================================================================================================
|
|
1498
|
+
function createStoreCreditPageGraph(binding) {
|
|
1499
|
+
const init = defineInit(binding, async (config, p) => {
|
|
1500
|
+
const { shopID, currency, opts } = config;
|
|
1501
|
+
return multiResponseToResponse(await requestMulti(getCustomerBalanceQuery)({ shopID, currency }, opts), (v) => {
|
|
1502
|
+
const { storefrontCustomerBalance: customerBalance, storefrontCustomerBalanceHistory: history } = v;
|
|
1503
|
+
return customerBalance && history
|
|
1504
|
+
? {
|
|
1505
|
+
customerBalance,
|
|
1506
|
+
history,
|
|
1507
|
+
currency,
|
|
1508
|
+
resetSuccess: p.previousPageKind !== "store_credit",
|
|
1509
|
+
}
|
|
1510
|
+
: undefined;
|
|
1511
|
+
});
|
|
1512
|
+
});
|
|
1513
|
+
const getPageFx = createEffect(async (p) => {
|
|
1514
|
+
const { shopID, opts } = p.config;
|
|
1515
|
+
return mapResponseData(await request(getCustomerBalanceHistoryPageQuery)({ shopID, ...p.data }, opts), (data) => {
|
|
1516
|
+
return { ...data, isFirstPage: p.data.lastKey === "", currency: p.data.currency };
|
|
1517
|
+
});
|
|
1518
|
+
});
|
|
1519
|
+
const setCurrency = createEvent();
|
|
1520
|
+
const loadMore = createEvent();
|
|
1521
|
+
const redeemedGiftCard = createEvent();
|
|
1522
|
+
const customerBalance = createStore(null).on(init.event, (_, v) => v.customerBalance);
|
|
1523
|
+
const history = createStore([]);
|
|
1524
|
+
const lastKey = createStore("");
|
|
1525
|
+
const historyCurrency = createStore("");
|
|
1526
|
+
const currency = createStore("");
|
|
1527
|
+
history.on(init.event, (_, v) => v.history.items);
|
|
1528
|
+
lastKey.on(init.event, (_, v) => v.history.last_key);
|
|
1529
|
+
historyCurrency.on(init.event, (_, v) => v.currency);
|
|
1530
|
+
currency.on(init.event, (_, v) => v.currency);
|
|
1531
|
+
// on currency change and if it's some new currency, reload history
|
|
1532
|
+
{
|
|
1533
|
+
const currencyChangeAccepted = guard({
|
|
1534
|
+
source: guard({
|
|
1535
|
+
source: sample(historyCurrency, setCurrency, (historyCurrency, currency) => ({ historyCurrency, currency })),
|
|
1536
|
+
filter: (source) => source.currency !== source.historyCurrency,
|
|
1537
|
+
}),
|
|
1538
|
+
filter: binding.everythingIdle,
|
|
1539
|
+
});
|
|
1540
|
+
forward({
|
|
1541
|
+
from: sample(binding.internalConfig, currencyChangeAccepted, (config, v) => ({
|
|
1542
|
+
config,
|
|
1543
|
+
data: { lastKey: "", currency: v.currency },
|
|
1544
|
+
})),
|
|
1545
|
+
to: getPageFx,
|
|
1546
|
+
});
|
|
1547
|
+
forward({
|
|
1548
|
+
from: currencyChangeAccepted.map((v) => v.currency),
|
|
1549
|
+
to: currency,
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
// on loadMore, sample lastKey, currency and fetch next page (if not already pending)
|
|
1553
|
+
guard({
|
|
1554
|
+
source: sample(combine({ config: binding.internalConfig, lastKey, historyCurrency }), loadMore, (s) => ({
|
|
1555
|
+
config: s.config,
|
|
1556
|
+
data: { lastKey: s.lastKey, currency: s.historyCurrency },
|
|
1557
|
+
})),
|
|
1558
|
+
filter: binding.everythingIdle,
|
|
1559
|
+
target: getPageFx,
|
|
1560
|
+
});
|
|
1561
|
+
const { data: getPageData, error: getPageError } = requestResponseSplit(getPageFx.doneData);
|
|
1562
|
+
// success: propagate new data to stores (note, last key is only applied when it's there)
|
|
1563
|
+
history.on(getPageData, (history, p) => (p.isFirstPage ? p.items : [...history, ...p.items]));
|
|
1564
|
+
lastKey.on(getPageData.filterMap((v) => v.last_key || undefined), (_, v) => v);
|
|
1565
|
+
historyCurrency.on(getPageData.map((v) => v.currency), (_, v) => v);
|
|
1566
|
+
// error: report unexpected error
|
|
1567
|
+
forward({ from: getPageError, to: binding.unexpectedError });
|
|
1568
|
+
// form
|
|
1569
|
+
const form = createFormWithCustomError({
|
|
1570
|
+
gift_card_code: createStringField("gift_card_code", "", [validNonEmpty]),
|
|
1571
|
+
}, null);
|
|
1572
|
+
const formToggleState = createFormToggleState(binding, form);
|
|
1573
|
+
formToggleState.isFormVisible.reset(init.event);
|
|
1574
|
+
forward({
|
|
1575
|
+
from: init.event,
|
|
1576
|
+
to: form.reset,
|
|
1577
|
+
});
|
|
1578
|
+
// create apply gift card effect and wire it to form
|
|
1579
|
+
const applyGiftCardFx = createEffect(async (p) => {
|
|
1580
|
+
const { shopID, opts } = p.config;
|
|
1581
|
+
return request(applyGiftCardMutation)({ shopID, data: p.data }, opts);
|
|
1582
|
+
});
|
|
1583
|
+
guard({
|
|
1584
|
+
source: sample(binding.internalConfig, form.submitted, (config, data) => ({ config, data })),
|
|
1585
|
+
filter: binding.everythingIdle,
|
|
1586
|
+
target: applyGiftCardFx,
|
|
1587
|
+
});
|
|
1588
|
+
const applyGiftCardResult = requestResponseSplit(applyGiftCardFx.doneData);
|
|
1589
|
+
// success
|
|
1590
|
+
forward({
|
|
1591
|
+
from: applyGiftCardResult.data,
|
|
1592
|
+
to: binding.reloadPage,
|
|
1593
|
+
});
|
|
1594
|
+
forward({
|
|
1595
|
+
from: applyGiftCardResult.data,
|
|
1596
|
+
to: redeemedGiftCard,
|
|
1597
|
+
});
|
|
1598
|
+
forward({
|
|
1599
|
+
from: applyGiftCardResult.data.map(() => false),
|
|
1600
|
+
to: formToggleState.isFormVisible,
|
|
1601
|
+
});
|
|
1602
|
+
// failure
|
|
1603
|
+
splitMap(applyGiftCardResult.error)
|
|
1604
|
+
.map((e) => (e.kind === "error" && e.error.apiError?.code === ErrorCode.NotFound ? "not_found" : undefined), form.setError)
|
|
1605
|
+
.fallback(handleFormFailure({ form, unexpectedError: binding.unexpectedError }));
|
|
1606
|
+
return {
|
|
1607
|
+
init,
|
|
1608
|
+
form,
|
|
1609
|
+
...formToggleState,
|
|
1610
|
+
customerBalance,
|
|
1611
|
+
somethingIsPending: combineSome(init.pending, applyGiftCardFx.pending, getPageFx.pending),
|
|
1612
|
+
redeemedGiftCard,
|
|
1613
|
+
setCurrency,
|
|
1614
|
+
currency,
|
|
1615
|
+
loadMore,
|
|
1616
|
+
historyCurrency,
|
|
1617
|
+
history,
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
//===================================================================================================================
|
|
1621
|
+
//===================================================================================================================
|
|
1622
|
+
//===================================================================================================================
|
|
1623
|
+
function createProfilePageGraph(binding) {
|
|
1624
|
+
const init = defineInit(binding, async (config, _p) => {
|
|
1625
|
+
const { shopID, opts } = config;
|
|
1626
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
1627
|
+
return mapResponseData(await request(getCustomerQuery)({ shopID, id: jwt.customer_id }, opts), (v) => ({
|
|
1628
|
+
customer: v[0],
|
|
1629
|
+
}));
|
|
1630
|
+
});
|
|
1631
|
+
const form = createForm({
|
|
1632
|
+
name: createStringField("name", "", [validNonEmpty, validMaxLength250]),
|
|
1633
|
+
display_name: createStringField("display_name", "", [validMaxLength250]),
|
|
1634
|
+
mobile: createStringField("mobile", "", []),
|
|
1635
|
+
mobile_notifications: createBooleanField("mobile_notifications", false),
|
|
1636
|
+
accepts_marketing: createBooleanField("accepts_marketing", false),
|
|
1637
|
+
});
|
|
1638
|
+
forward({
|
|
1639
|
+
from: init.event.map((v) => ({
|
|
1640
|
+
name: v.customer.name,
|
|
1641
|
+
display_name: v.customer.display_name,
|
|
1642
|
+
mobile: v.customer.mobile,
|
|
1643
|
+
mobile_notifications: v.customer.mobile_notifications,
|
|
1644
|
+
accepts_marketing: v.customer.accepts_marketing,
|
|
1645
|
+
})),
|
|
1646
|
+
to: form.init,
|
|
1647
|
+
});
|
|
1648
|
+
// submit form API call
|
|
1649
|
+
const saveFx = createEffect(async (p) => {
|
|
1650
|
+
const { shopID, opts } = p.config;
|
|
1651
|
+
const jwt = jwtDecode(nonNull(opts?.authToken, "auth token"));
|
|
1652
|
+
return request(modifyCustomerMutation)({ shopID, id: jwt.customer_id, data: p.data }, opts);
|
|
1653
|
+
});
|
|
1654
|
+
guard({
|
|
1655
|
+
source: sample(binding.internalConfig, form.submitted, (config, data) => ({ config, data })),
|
|
1656
|
+
filter: binding.everythingIdle,
|
|
1657
|
+
target: saveFx,
|
|
1658
|
+
});
|
|
1659
|
+
const { data: saveData, error: saveError } = requestResponseSplit(saveFx.doneData);
|
|
1660
|
+
// success
|
|
1661
|
+
forward({ from: saveData, to: binding.reloadPage });
|
|
1662
|
+
// failure
|
|
1663
|
+
handleFormFailure({ source: saveError, form, unexpectedError: binding.unexpectedError }, { from: "[0]." });
|
|
1664
|
+
return {
|
|
1665
|
+
init,
|
|
1666
|
+
form,
|
|
1667
|
+
somethingIsPending: combineSome(init.pending, saveFx.pending),
|
|
1668
|
+
};
|
|
1669
|
+
}
|
|
1670
|
+
//===================================================================================================================
|
|
1671
|
+
//===================================================================================================================
|
|
1672
|
+
//===================================================================================================================
|
|
1673
|
+
function createSigninPageGraph(binding) {
|
|
1674
|
+
const init = defineInitBlank(binding);
|
|
1675
|
+
const setSignInMode = createEvent();
|
|
1676
|
+
const signInMode = restore(setSignInMode, "email-otp-init");
|
|
1677
|
+
const form = createFormWithCustomError({
|
|
1678
|
+
email: createStringField("email", "", [validNonEmpty, validEmail, validMaxLength250]),
|
|
1679
|
+
password: createStringField("password", "", [validNonEmpty]),
|
|
1680
|
+
}, null);
|
|
1681
|
+
const formOTPInit = createFormWithCustomError({
|
|
1682
|
+
email: createStringField("email", "", [validNonEmpty, validEmail, validMaxLength250]),
|
|
1683
|
+
}, null);
|
|
1684
|
+
const formOTPComplete = createFormWithCustomError({
|
|
1685
|
+
code: createStringField("code", "", [validNonEmpty, validMaxLength250]),
|
|
1686
|
+
}, null);
|
|
1687
|
+
forward({
|
|
1688
|
+
from: init.event,
|
|
1689
|
+
to: [form.reset, formOTPInit.reset, formOTPComplete.reset],
|
|
1690
|
+
});
|
|
1691
|
+
signInMode.reset(init.event);
|
|
1692
|
+
const signinFx = createEffect(async (p) => {
|
|
1693
|
+
const { shopID, opts } = p.config;
|
|
1694
|
+
return request(signInMutation)({ shopID, data: p.data }, opts);
|
|
1695
|
+
});
|
|
1696
|
+
guard({
|
|
1697
|
+
source: sample(binding.internalConfig, form.submitted, (config, data) => ({ config, data })),
|
|
1698
|
+
filter: binding.everythingIdle,
|
|
1699
|
+
target: signinFx,
|
|
1700
|
+
});
|
|
1701
|
+
const signInViaEmailInitFx = createEffect(async (p) => {
|
|
1702
|
+
const { shopID, opts } = p.config;
|
|
1703
|
+
return request(signInViaEmailInitMutation)({ shopID, data: p.data }, opts);
|
|
1704
|
+
});
|
|
1705
|
+
guard({
|
|
1706
|
+
source: sample(binding.internalConfig, formOTPInit.submitted, (config, data) => ({
|
|
1707
|
+
config,
|
|
1708
|
+
data: { ...data, timezone_hint: getTimezone() },
|
|
1709
|
+
})),
|
|
1710
|
+
filter: binding.everythingIdle,
|
|
1711
|
+
target: signInViaEmailInitFx,
|
|
1712
|
+
});
|
|
1713
|
+
const signInViaEmailCompleteFx = createEffect(async (p) => {
|
|
1714
|
+
const { shopID, opts } = p.config;
|
|
1715
|
+
return request(signInViaEmailCompleteMutation)({ shopID, data: p.data }, opts);
|
|
1716
|
+
});
|
|
1717
|
+
guard({
|
|
1718
|
+
source: sample(combine({ config: binding.internalConfig, email: formOTPInit.email.value }), formOTPComplete.submitted, ({ config, email }, data) => ({ config, data: { ...data, email } })),
|
|
1719
|
+
filter: binding.everythingIdle,
|
|
1720
|
+
target: signInViaEmailCompleteFx,
|
|
1721
|
+
});
|
|
1722
|
+
// email/password form
|
|
1723
|
+
{
|
|
1724
|
+
const { data: signinData } = requestResponseSplit(signinFx.doneData);
|
|
1725
|
+
// success
|
|
1726
|
+
forward({
|
|
1727
|
+
from: signinData.filterMap((v) => v.token || undefined),
|
|
1728
|
+
to: binding.setJWT,
|
|
1729
|
+
});
|
|
1730
|
+
// failure
|
|
1731
|
+
splitMap(signinFx.done)
|
|
1732
|
+
.map((e) => e.result.kind === "error" && e.result.error.apiError?.code === ErrorCode.Unauthorized
|
|
1733
|
+
? e.params.data.email
|
|
1734
|
+
? "unauthorized"
|
|
1735
|
+
: "unauthorized_oauth"
|
|
1736
|
+
: undefined, form.setError)
|
|
1737
|
+
.map((e) => (e.result.kind !== "data" ? e.result : undefined), handleFormFailure({ form, unexpectedError: binding.unexpectedError }));
|
|
1738
|
+
}
|
|
1739
|
+
// OTP init form
|
|
1740
|
+
{
|
|
1741
|
+
const { data, error } = requestResponseSplit(signInViaEmailInitFx.doneData);
|
|
1742
|
+
// success
|
|
1743
|
+
forward({
|
|
1744
|
+
from: data.map(() => "email-otp-complete"),
|
|
1745
|
+
to: setSignInMode,
|
|
1746
|
+
});
|
|
1747
|
+
// failure
|
|
1748
|
+
splitMap(error)
|
|
1749
|
+
.map((e) => e.kind === "error" && e.error.apiError?.code === ErrorCode.TryAgainLater ? "try_again_later" : undefined, formOTPInit.setError)
|
|
1750
|
+
.fallback(handleFormFailure({ form: formOTPInit, unexpectedError: binding.unexpectedError }));
|
|
1751
|
+
}
|
|
1752
|
+
// OTP complete form
|
|
1753
|
+
{
|
|
1754
|
+
const { data, error } = requestResponseSplit(signInViaEmailCompleteFx.doneData);
|
|
1755
|
+
// success
|
|
1756
|
+
forward({
|
|
1757
|
+
from: data.filterMap((v) => v.token || undefined),
|
|
1758
|
+
to: binding.setJWT,
|
|
1759
|
+
});
|
|
1760
|
+
// failure
|
|
1761
|
+
splitMap(error)
|
|
1762
|
+
.map((e) => (e.kind === "error" && e.error.apiError?.code === ErrorCode.NotFound ? "unauthorized" : undefined), formOTPComplete.setError)
|
|
1763
|
+
.fallback(handleFormFailure({ form: formOTPComplete, unexpectedError: binding.unexpectedError }));
|
|
1764
|
+
}
|
|
1765
|
+
// oauth flow
|
|
1766
|
+
const oauth2Click = createEvent();
|
|
1767
|
+
guard({
|
|
1768
|
+
source: oauth2Click.map((kind) => ({ kind, route: "signin" })),
|
|
1769
|
+
filter: binding.everythingIdle,
|
|
1770
|
+
target: binding.oauth2.requestFx,
|
|
1771
|
+
});
|
|
1772
|
+
guard({
|
|
1773
|
+
source: sample(binding.internalConfig, binding.oauth2.requestFx.doneData.filterMap((r) => r.route === "signin" && r.response.kind === "success"
|
|
1774
|
+
? { oauth_provider: r.kind, oauth_code: r.response.code, timezone_hint: getTimezone() }
|
|
1775
|
+
: r.route === "signin" && r.response.kind === "success_oauth1"
|
|
1776
|
+
? {
|
|
1777
|
+
oauth_provider: r.kind,
|
|
1778
|
+
oauth_token: r.response.token,
|
|
1779
|
+
oauth_verifier: r.response.verifier,
|
|
1780
|
+
timezone_hint: getTimezone(),
|
|
1781
|
+
}
|
|
1782
|
+
: undefined), (config, data) => ({ config, data })),
|
|
1783
|
+
filter: binding.everythingIdle,
|
|
1784
|
+
target: signinFx,
|
|
1785
|
+
});
|
|
1786
|
+
return {
|
|
1787
|
+
init,
|
|
1788
|
+
form,
|
|
1789
|
+
formOTPInit,
|
|
1790
|
+
formOTPComplete,
|
|
1791
|
+
signInMode,
|
|
1792
|
+
setSignInMode,
|
|
1793
|
+
oauth2Click,
|
|
1794
|
+
somethingIsPending: combineSome(init.pending, signinFx.pending),
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
function createOAuth2RequestGraph(config) {
|
|
1798
|
+
const cancelFuncs = [];
|
|
1799
|
+
const cancel = createEvent();
|
|
1800
|
+
cancel.watch(() => {
|
|
1801
|
+
for (const c of cancelFuncs) {
|
|
1802
|
+
c();
|
|
1803
|
+
}
|
|
1804
|
+
});
|
|
1805
|
+
const requestFx = createEffect(async (req) => {
|
|
1806
|
+
const randomToken = generateRandomToken();
|
|
1807
|
+
if (!config.oauth2)
|
|
1808
|
+
return { kind: req.kind, route: req.route, response: { kind: "failure" } };
|
|
1809
|
+
const [requestPromise, cancelFunc] = config.oauth2.request({ kind: req.kind, randomToken });
|
|
1810
|
+
cancelFuncs.push(cancelFunc);
|
|
1811
|
+
const r = await requestPromise;
|
|
1812
|
+
{
|
|
1813
|
+
// TODO: is it safe?
|
|
1814
|
+
const i = cancelFuncs.findIndex((f) => f === cancelFunc);
|
|
1815
|
+
if (i !== -1) {
|
|
1816
|
+
cancelFuncs.splice(i, 1);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
return { kind: req.kind, route: req.route, response: r };
|
|
1820
|
+
});
|
|
1821
|
+
const providers = createStore([...(config.oauth2?.providers || [])]);
|
|
1822
|
+
return {
|
|
1823
|
+
providers,
|
|
1824
|
+
cancel,
|
|
1825
|
+
requestFx,
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
//===================================================================================================================
|
|
1829
|
+
//===================================================================================================================
|
|
1830
|
+
//===================================================================================================================
|
|
1831
|
+
// not really a part of any page, but somewhat follows page graph conventions, except it doesn't have init.
|
|
1832
|
+
function createOAuth2UtilsGraph(binding) {
|
|
1833
|
+
const ROUTE = "connect";
|
|
1834
|
+
const connectOAuth2 = createEvent();
|
|
1835
|
+
const disconnectOAuth2 = createEvent();
|
|
1836
|
+
const connectFx = createEffect(async (p) => {
|
|
1837
|
+
const { shopID, opts } = p.config;
|
|
1838
|
+
return request(connectOAuth2Mutation)({ shopID, ...p.data }, opts);
|
|
1839
|
+
});
|
|
1840
|
+
const disconnectFx = createEffect(async (p) => {
|
|
1841
|
+
const { shopID, opts } = p.config;
|
|
1842
|
+
return request(disconnectOAuth2Mutation)({ shopID }, opts);
|
|
1843
|
+
});
|
|
1844
|
+
// connect flow
|
|
1845
|
+
{
|
|
1846
|
+
guard({
|
|
1847
|
+
source: connectOAuth2.map((kind) => ({ kind, route: ROUTE })),
|
|
1848
|
+
filter: binding.everythingIdle,
|
|
1849
|
+
target: binding.oauth2.requestFx,
|
|
1850
|
+
});
|
|
1851
|
+
guard({
|
|
1852
|
+
source: sample(binding.internalConfig, binding.oauth2.requestFx.doneData.filterMap((r) => r.route === ROUTE && r.response.kind === "success"
|
|
1853
|
+
? { provider: r.kind, code: r.response.code }
|
|
1854
|
+
: r.route === ROUTE && r.response.kind === "success_oauth1"
|
|
1855
|
+
? { provider: r.kind, token: r.response.token, verifier: r.response.verifier }
|
|
1856
|
+
: undefined), (config, data) => ({ config, data })),
|
|
1857
|
+
filter: binding.everythingIdle,
|
|
1858
|
+
target: connectFx,
|
|
1859
|
+
});
|
|
1860
|
+
const { data: connectData, error: connectError } = requestResponseSplit(connectFx.doneData);
|
|
1861
|
+
// success
|
|
1862
|
+
forward({
|
|
1863
|
+
from: connectData,
|
|
1864
|
+
to: binding.fetchCustomerInfoNow,
|
|
1865
|
+
});
|
|
1866
|
+
forward({
|
|
1867
|
+
from: connectData.map(() => "oauth2_connected"),
|
|
1868
|
+
to: binding.message,
|
|
1869
|
+
});
|
|
1870
|
+
// failure
|
|
1871
|
+
forward({
|
|
1872
|
+
from: connectError,
|
|
1873
|
+
to: binding.unexpectedError,
|
|
1874
|
+
});
|
|
1875
|
+
}
|
|
1876
|
+
// disconnect flow
|
|
1877
|
+
{
|
|
1878
|
+
guard({
|
|
1879
|
+
source: sample(binding.internalConfig, disconnectOAuth2, (config, data) => ({ config, data })),
|
|
1880
|
+
filter: binding.everythingIdle,
|
|
1881
|
+
target: disconnectFx,
|
|
1882
|
+
});
|
|
1883
|
+
const { data: disconnectData, error: disconnectError } = requestResponseSplit(disconnectFx.doneData);
|
|
1884
|
+
// success
|
|
1885
|
+
forward({
|
|
1886
|
+
from: disconnectData,
|
|
1887
|
+
to: binding.fetchCustomerInfoNow,
|
|
1888
|
+
});
|
|
1889
|
+
forward({
|
|
1890
|
+
from: disconnectData.map(() => "oauth2_disconnected"),
|
|
1891
|
+
to: binding.message,
|
|
1892
|
+
});
|
|
1893
|
+
// failure
|
|
1894
|
+
forward({
|
|
1895
|
+
from: disconnectError,
|
|
1896
|
+
to: binding.unexpectedError,
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1899
|
+
return {
|
|
1900
|
+
connectOAuth2,
|
|
1901
|
+
disconnectOAuth2,
|
|
1902
|
+
somethingIsPending: combineSome(connectFx.pending, disconnectFx.pending),
|
|
1903
|
+
};
|
|
1904
|
+
}
|
|
1905
|
+
export function createCustomer(config, init) {
|
|
1906
|
+
const currency = config.currency || createStore(config.shopCurrency);
|
|
1907
|
+
const oauth2 = createOAuth2RequestGraph(config);
|
|
1908
|
+
const setCustomerInfo = createEvent();
|
|
1909
|
+
const customerInfo = createStore(null).on(setCustomerInfo, (_, v) => v);
|
|
1910
|
+
const everythingIdle = createStore(true);
|
|
1911
|
+
const internalConfig = combine({
|
|
1912
|
+
jwt: config.jwt,
|
|
1913
|
+
locale: config.locale,
|
|
1914
|
+
currency,
|
|
1915
|
+
}, ({ jwt, locale, currency }) => ({
|
|
1916
|
+
shopID: config.shopID,
|
|
1917
|
+
oauth2: config.oauth2,
|
|
1918
|
+
stripePromise: config.stripePromise,
|
|
1919
|
+
currency,
|
|
1920
|
+
opts: {
|
|
1921
|
+
...config.opts,
|
|
1922
|
+
authToken: jwt,
|
|
1923
|
+
locale,
|
|
1924
|
+
},
|
|
1925
|
+
}));
|
|
1926
|
+
const getCustomerInfoFx = createEffect(async (cfg) => {
|
|
1927
|
+
const { shopID, opts } = cfg;
|
|
1928
|
+
let customerID = "";
|
|
1929
|
+
try {
|
|
1930
|
+
customerID = jwtDecode(nonNull(opts?.authToken, "auth token"))?.customer_id || "";
|
|
1931
|
+
}
|
|
1932
|
+
catch {
|
|
1933
|
+
// do nothing
|
|
1934
|
+
}
|
|
1935
|
+
return getCustomerInfo(shopID, customerID, opts);
|
|
1936
|
+
});
|
|
1937
|
+
forward({
|
|
1938
|
+
from: getCustomerInfoFx.doneData,
|
|
1939
|
+
to: customerInfo,
|
|
1940
|
+
});
|
|
1941
|
+
forward({
|
|
1942
|
+
from: internalConfig,
|
|
1943
|
+
to: getCustomerInfoFx,
|
|
1944
|
+
});
|
|
1945
|
+
const fetchCustomerInfoNow = createEvent();
|
|
1946
|
+
forward({
|
|
1947
|
+
from: sample(internalConfig, fetchCustomerInfoNow),
|
|
1948
|
+
to: getCustomerInfoFx,
|
|
1949
|
+
});
|
|
1950
|
+
const unexpectedError = createEvent();
|
|
1951
|
+
const setJWT = createEvent();
|
|
1952
|
+
const setFavorites = createEvent();
|
|
1953
|
+
const addFavoriteToInfo = createEvent();
|
|
1954
|
+
const modifyFavoriteInInfo = createEvent();
|
|
1955
|
+
const removeFavoriteFromInfo = createEvent();
|
|
1956
|
+
const reloadPage = createEvent();
|
|
1957
|
+
const reloadPageIfActive = createEvent();
|
|
1958
|
+
const internalGoTo = createEvent();
|
|
1959
|
+
const externalGoTo = createEvent();
|
|
1960
|
+
const message = createEvent();
|
|
1961
|
+
const binding = {
|
|
1962
|
+
everythingIdle,
|
|
1963
|
+
internalConfig,
|
|
1964
|
+
unexpectedError,
|
|
1965
|
+
setJWT,
|
|
1966
|
+
setFavorites,
|
|
1967
|
+
addFavoriteToInfo,
|
|
1968
|
+
modifyFavoriteInInfo,
|
|
1969
|
+
removeFavoriteFromInfo,
|
|
1970
|
+
reloadPage,
|
|
1971
|
+
reloadPageIfActive,
|
|
1972
|
+
goTo: internalGoTo,
|
|
1973
|
+
message,
|
|
1974
|
+
fetchCustomerInfoNow,
|
|
1975
|
+
oauth2,
|
|
1976
|
+
};
|
|
1977
|
+
config.jwt.on(setJWT, (_, v) => v);
|
|
1978
|
+
customerInfo.on(setFavorites, (pv, favorites) => {
|
|
1979
|
+
if (!pv)
|
|
1980
|
+
return null;
|
|
1981
|
+
return { ...pv, favorites };
|
|
1982
|
+
});
|
|
1983
|
+
customerInfo.on(addFavoriteToInfo, (pv, v) => {
|
|
1984
|
+
if (!pv)
|
|
1985
|
+
return null;
|
|
1986
|
+
if (pv.favorites.find((f) => f.id === v.id))
|
|
1987
|
+
return pv;
|
|
1988
|
+
return {
|
|
1989
|
+
...pv,
|
|
1990
|
+
favorites: [...pv.favorites, v],
|
|
1991
|
+
};
|
|
1992
|
+
});
|
|
1993
|
+
customerInfo.on(modifyFavoriteInInfo, (pv, v) => {
|
|
1994
|
+
if (!pv)
|
|
1995
|
+
return null;
|
|
1996
|
+
const newFavs = [...pv.favorites];
|
|
1997
|
+
const idx = newFavs.findIndex((f) => f.id === v.id);
|
|
1998
|
+
if (idx !== -1) {
|
|
1999
|
+
newFavs[idx] = { ...newFavs[idx], ...v };
|
|
2000
|
+
}
|
|
2001
|
+
return {
|
|
2002
|
+
...pv,
|
|
2003
|
+
favorites: newFavs,
|
|
2004
|
+
};
|
|
2005
|
+
});
|
|
2006
|
+
customerInfo.on(removeFavoriteFromInfo, (pv, v) => {
|
|
2007
|
+
if (!pv)
|
|
2008
|
+
return null;
|
|
2009
|
+
return {
|
|
2010
|
+
...pv,
|
|
2011
|
+
favorites: pv.favorites.filter((f) => f.id !== v),
|
|
2012
|
+
};
|
|
2013
|
+
});
|
|
2014
|
+
// on locale changes, reload the page
|
|
2015
|
+
forward({
|
|
2016
|
+
from: config.locale.updates,
|
|
2017
|
+
to: reloadPage,
|
|
2018
|
+
});
|
|
2019
|
+
const pages = {
|
|
2020
|
+
signin: createSigninPageGraph(binding),
|
|
2021
|
+
signup: createSignupPageGraph(binding),
|
|
2022
|
+
resetPassword: createResetPasswordPageGraph(binding),
|
|
2023
|
+
addresses: createAddressesPageGraph(binding),
|
|
2024
|
+
favorites: createFavoritesPageGraph(binding),
|
|
2025
|
+
orders: createOrdersPageGraph(binding),
|
|
2026
|
+
subscriptions: createSubscriptionsPageGraph(binding),
|
|
2027
|
+
returns: createReturnsPageGraph(binding),
|
|
2028
|
+
order: createOrderPageGraph(binding),
|
|
2029
|
+
subscription: createSubscriptionPageGraph(binding),
|
|
2030
|
+
return: createReturnPageGraph(binding),
|
|
2031
|
+
createReturn: createCreateReturnPageGraph(binding),
|
|
2032
|
+
storeCredit: createStoreCreditPageGraph(binding),
|
|
2033
|
+
profile: createProfilePageGraph(binding),
|
|
2034
|
+
paymentMethods: createPaymentMethodsPageGraph(binding),
|
|
2035
|
+
};
|
|
2036
|
+
const oauth2Utils = createOAuth2UtilsGraph(binding);
|
|
2037
|
+
const currentPage = createStore(null);
|
|
2038
|
+
const loadPage = createEvent();
|
|
2039
|
+
const loadPageExt = sample(currentPage, loadPage, (p, param) => ({
|
|
2040
|
+
previousPageKind: p?.kind || null,
|
|
2041
|
+
param,
|
|
2042
|
+
}));
|
|
2043
|
+
const loadSignin = loadPageExt.filterMap((v) => (v.param.kind === "signin" ? { ...v, param: v.param } : undefined));
|
|
2044
|
+
const loadSignup = loadPageExt.filterMap((v) => (v.param.kind === "signup" ? { ...v, param: v.param } : undefined));
|
|
2045
|
+
const loadResetPassword = loadPageExt.filterMap((v) => v.param.kind === "reset_password" ? { ...v, param: v.param } : undefined);
|
|
2046
|
+
const loadAddresses = loadPageExt.filterMap((v) => v.param.kind === "addresses" ? { ...v, param: v.param } : undefined);
|
|
2047
|
+
const loadFavorites = loadPageExt.filterMap((v) => v.param.kind === "favorites" ? { ...v, param: v.param } : undefined);
|
|
2048
|
+
const loadOrders = loadPageExt.filterMap((v) => (v.param.kind === "orders" ? { ...v, param: v.param } : undefined));
|
|
2049
|
+
const loadSubscriptions = loadPageExt.filterMap((v) => v.param.kind === "subscriptions" ? { ...v, param: v.param } : undefined);
|
|
2050
|
+
const loadReturns = loadPageExt.filterMap((v) => (v.param.kind === "returns" ? { ...v, param: v.param } : undefined));
|
|
2051
|
+
const loadOrder = loadPageExt.filterMap((v) => (v.param.kind === "order" ? { ...v, param: v.param } : undefined));
|
|
2052
|
+
const loadSubscription = loadPageExt.filterMap((v) => v.param.kind === "subscription" ? { ...v, param: v.param } : undefined);
|
|
2053
|
+
const loadReturn = loadPageExt.filterMap((v) => (v.param.kind === "return" ? { ...v, param: v.param } : undefined));
|
|
2054
|
+
const loadCreateReturn = loadPageExt.filterMap((v) => v.param.kind === "create_return" ? { ...v, param: v.param } : undefined);
|
|
2055
|
+
const loadStoreCredit = loadPageExt.filterMap((v) => v.param.kind === "store_credit" ? { ...v, param: v.param } : undefined);
|
|
2056
|
+
const loadProfile = loadPageExt.filterMap((v) => (v.param.kind === "profile" ? { ...v, param: v.param } : undefined));
|
|
2057
|
+
const loadPaymentMethods = loadPageExt.filterMap((v) => v.param.kind === "payment_methods" ? { ...v, param: v.param } : undefined);
|
|
2058
|
+
forward({ from: loadSignin, to: pages.signin.init.load });
|
|
2059
|
+
forward({ from: loadSignup, to: pages.signup.init.load });
|
|
2060
|
+
forward({ from: loadResetPassword, to: pages.resetPassword.init.load });
|
|
2061
|
+
forward({ from: loadAddresses, to: pages.addresses.init.load });
|
|
2062
|
+
forward({ from: loadFavorites, to: pages.favorites.init.load });
|
|
2063
|
+
forward({ from: loadOrders, to: pages.orders.init.load });
|
|
2064
|
+
forward({ from: loadSubscriptions, to: pages.subscriptions.init.load });
|
|
2065
|
+
forward({ from: loadReturns, to: pages.returns.init.load });
|
|
2066
|
+
forward({ from: loadOrder, to: pages.order.init.load });
|
|
2067
|
+
forward({ from: loadSubscription, to: pages.subscription.init.load });
|
|
2068
|
+
forward({ from: loadReturn, to: pages.return.init.load });
|
|
2069
|
+
forward({ from: loadCreateReturn, to: pages.createReturn.init.load });
|
|
2070
|
+
forward({ from: loadStoreCredit, to: pages.storeCredit.init.load });
|
|
2071
|
+
forward({ from: loadProfile, to: pages.profile.init.load });
|
|
2072
|
+
forward({ from: loadPaymentMethods, to: pages.paymentMethods.init.load });
|
|
2073
|
+
const lastAuthPage = createStore(null);
|
|
2074
|
+
lastAuthPage.on(externalGoTo.filter({ fn: (pp) => pp === null || !disallowedLastAuthPages[pp.kind] }), (_, v) => v);
|
|
2075
|
+
const jwtAndCurrentPage = combine(config.jwt, currentPage);
|
|
2076
|
+
const jwtAndCurrentPageAndLastAuthPage = combine(config.jwt, currentPage, lastAuthPage);
|
|
2077
|
+
forward({
|
|
2078
|
+
from: [
|
|
2079
|
+
pages.signin.init.loaded,
|
|
2080
|
+
pages.signup.init.loaded,
|
|
2081
|
+
pages.resetPassword.init.loaded,
|
|
2082
|
+
pages.addresses.init.loaded,
|
|
2083
|
+
pages.favorites.init.loaded,
|
|
2084
|
+
pages.orders.init.loaded,
|
|
2085
|
+
pages.subscriptions.init.loaded,
|
|
2086
|
+
pages.returns.init.loaded,
|
|
2087
|
+
pages.order.init.loaded,
|
|
2088
|
+
pages.subscription.init.loaded,
|
|
2089
|
+
pages.return.init.loaded,
|
|
2090
|
+
pages.createReturn.init.loaded,
|
|
2091
|
+
pages.storeCredit.init.loaded,
|
|
2092
|
+
pages.profile.init.loaded,
|
|
2093
|
+
pages.paymentMethods.init.loaded,
|
|
2094
|
+
],
|
|
2095
|
+
to: currentPage,
|
|
2096
|
+
});
|
|
2097
|
+
const somethingPending = combineSome(pages.signin.somethingIsPending, pages.signup.somethingIsPending, pages.resetPassword.somethingIsPending, pages.addresses.somethingIsPending, pages.favorites.somethingIsPending, pages.orders.somethingIsPending, pages.subscriptions.somethingIsPending, pages.returns.somethingIsPending, pages.order.somethingIsPending, pages.subscription.somethingIsPending, pages.return.somethingIsPending, pages.createReturn.somethingIsPending, pages.storeCredit.somethingIsPending, pages.profile.somethingIsPending, pages.paymentMethods.somethingIsPending, oauth2Utils.somethingIsPending);
|
|
2098
|
+
forward({
|
|
2099
|
+
from: somethingPending.map((v) => !v),
|
|
2100
|
+
to: everythingIdle,
|
|
2101
|
+
});
|
|
2102
|
+
const logout = createEvent();
|
|
2103
|
+
// goTo triggers loadPage, but with possible redirect based on jwt
|
|
2104
|
+
sample({
|
|
2105
|
+
source: config.jwt,
|
|
2106
|
+
clock: internalGoTo,
|
|
2107
|
+
fn: (jwt, pageParam) => shouldRedirect(jwt, pageParam) || pageParam,
|
|
2108
|
+
target: loadPage,
|
|
2109
|
+
});
|
|
2110
|
+
// on page reload, just "goTo" "currentPage"
|
|
2111
|
+
forward({
|
|
2112
|
+
from: sample(currentPage, reloadPage).filterMap((v) => v || undefined),
|
|
2113
|
+
to: internalGoTo,
|
|
2114
|
+
});
|
|
2115
|
+
// optional page reload
|
|
2116
|
+
forward({
|
|
2117
|
+
from: sample(currentPage, reloadPageIfActive, (currentPage, target) => ({ currentPage, target })).filterMap(({ currentPage, target }) => (currentPage?.kind === target ? currentPage : undefined)),
|
|
2118
|
+
to: internalGoTo,
|
|
2119
|
+
});
|
|
2120
|
+
// Based on "jwt"/"currentPage" state, kick us out from pages we're not allowed to be in.
|
|
2121
|
+
// It's unlikely that we get here due to "currentPage" changes, because goToFx also handles this.
|
|
2122
|
+
// However, when "jwt" changes, we might end up being on a wrong page.
|
|
2123
|
+
forward({
|
|
2124
|
+
from: jwtAndCurrentPageAndLastAuthPage.updates.filterMap(([jwt, currentPage, lastAuthPage]) => currentPage ? shouldRedirect(jwt, currentPage, lastAuthPage) : undefined),
|
|
2125
|
+
to: internalGoTo,
|
|
2126
|
+
});
|
|
2127
|
+
// expose only "logout" via API
|
|
2128
|
+
guard({
|
|
2129
|
+
source: logout.map(() => ""),
|
|
2130
|
+
filter: everythingIdle,
|
|
2131
|
+
target: setJWT,
|
|
2132
|
+
});
|
|
2133
|
+
guard({
|
|
2134
|
+
source: logout.map(() => ({ kind: "signin", action: "push" })),
|
|
2135
|
+
filter: everythingIdle,
|
|
2136
|
+
target: internalGoTo,
|
|
2137
|
+
});
|
|
2138
|
+
// start with signin page (will be redirected for logged in customer)
|
|
2139
|
+
if (init.kind === "goto") {
|
|
2140
|
+
internalGoTo(init.dest);
|
|
2141
|
+
}
|
|
2142
|
+
else if (init.kind === "default") {
|
|
2143
|
+
internalGoTo({ kind: "signin", action: "push" });
|
|
2144
|
+
}
|
|
2145
|
+
{
|
|
2146
|
+
const cfg = internalConfig.getState();
|
|
2147
|
+
let persistLoaded = false;
|
|
2148
|
+
if (config.persist) {
|
|
2149
|
+
const VERSION = 1;
|
|
2150
|
+
const { load, save, onChange, maxAgeMs } = config.persist;
|
|
2151
|
+
const realMaxAgeMs = Math.max(maxAgeMs ?? 0, 0) || 1800000;
|
|
2152
|
+
{
|
|
2153
|
+
const ci = deserialize(load(), VERSION, realMaxAgeMs);
|
|
2154
|
+
if (ci !== undefined) {
|
|
2155
|
+
setCustomerInfo(ci);
|
|
2156
|
+
persistLoaded = true;
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
customerInfo.updates.watch((data) => {
|
|
2160
|
+
save(serialize(data, VERSION));
|
|
2161
|
+
});
|
|
2162
|
+
onChange((data) => {
|
|
2163
|
+
const ci = deserialize(data, VERSION, realMaxAgeMs);
|
|
2164
|
+
if (ci !== undefined) {
|
|
2165
|
+
setCustomerInfo(ci);
|
|
2166
|
+
}
|
|
2167
|
+
});
|
|
2168
|
+
}
|
|
2169
|
+
if (cfg.opts?.authToken && !persistLoaded) {
|
|
2170
|
+
fetchCustomerInfoNow();
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
forward({
|
|
2174
|
+
from: externalGoTo,
|
|
2175
|
+
to: internalGoTo,
|
|
2176
|
+
});
|
|
2177
|
+
// customerMenuVisible helper
|
|
2178
|
+
const customerLoggedIn = jwtAndCurrentPage.map(([jwt, currentPage]) => jwt !== "" && currentPage && currentPage.kind !== "signin" && currentPage.kind !== "signup");
|
|
2179
|
+
return {
|
|
2180
|
+
message,
|
|
2181
|
+
logout,
|
|
2182
|
+
currentPage,
|
|
2183
|
+
customerLoggedIn,
|
|
2184
|
+
customerInfo,
|
|
2185
|
+
goTo: externalGoTo,
|
|
2186
|
+
unexpectedError,
|
|
2187
|
+
reloadPage,
|
|
2188
|
+
pages,
|
|
2189
|
+
somethingPending,
|
|
2190
|
+
oauth2: {
|
|
2191
|
+
cancel: oauth2.cancel,
|
|
2192
|
+
pending: oauth2.requestFx.pending,
|
|
2193
|
+
providers: oauth2.providers,
|
|
2194
|
+
connect: oauth2Utils.connectOAuth2,
|
|
2195
|
+
disconnect: oauth2Utils.disconnectOAuth2,
|
|
2196
|
+
},
|
|
2197
|
+
};
|
|
2198
|
+
}
|