@beamimpact/web-sdk 1.58.1 → 1.58.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{_share-dialog-dependencies-DPid-O65.esm.js → _share-dialog-dependencies-C3oAeUgm.esm.js} +2 -2
- package/dist/chunks/{_share-dialog-dependencies-DPid-O65.esm.js.map → _share-dialog-dependencies-C3oAeUgm.esm.js.map} +1 -1
- package/dist/chunks/{index-DnFFgYbT.esm.js → index-B2GUlwwp.esm.js} +2 -2
- package/dist/chunks/{index-DnFFgYbT.esm.js.map → index-B2GUlwwp.esm.js.map} +1 -1
- package/dist/chunks/{index-BygeMtqf.esm.js → index-BhlTVL8_.esm.js} +2 -2
- package/dist/chunks/{index-BygeMtqf.esm.js.map → index-BhlTVL8_.esm.js.map} +1 -1
- package/dist/chunks/{index-tkscjKkq.esm.js → index-BlaOItQr.esm.js} +2 -2
- package/dist/chunks/{index-tkscjKkq.esm.js.map → index-BlaOItQr.esm.js.map} +1 -1
- package/dist/chunks/{index-BiOlmhqL.esm.js → index-BtG64tE0.esm.js} +2 -2
- package/dist/chunks/{index-BiOlmhqL.esm.js.map → index-BtG64tE0.esm.js.map} +1 -1
- package/dist/chunks/{index-lSPlMuMz.esm.js → index-C6QfHWnX.esm.js} +2 -2
- package/dist/chunks/{index-lSPlMuMz.esm.js.map → index-C6QfHWnX.esm.js.map} +1 -1
- package/dist/chunks/{index-C8pScO8d.esm.js → index-DC8IegOb.esm.js} +2 -2
- package/dist/chunks/{index-C8pScO8d.esm.js.map → index-DC8IegOb.esm.js.map} +1 -1
- package/dist/chunks/{index-CsNyA6Px.esm.js → index-PWwahCdj.esm.js} +2 -2
- package/dist/chunks/{index-CsNyA6Px.esm.js.map → index-PWwahCdj.esm.js.map} +1 -1
- package/dist/chunks/{index-U1QpwjdF.esm.js → index-hCVICwBS.esm.js} +2 -2
- package/dist/chunks/{index-U1QpwjdF.esm.js.map → index-hCVICwBS.esm.js.map} +1 -1
- package/dist/chunks/{promo-pill-label-DYR3PZH7.esm.js → promo-pill-label-rA01UjBk.esm.js} +2 -2
- package/dist/chunks/{promo-pill-label-DYR3PZH7.esm.js.map → promo-pill-label-rA01UjBk.esm.js.map} +1 -1
- package/dist/chunks/{share-button-DP2wLhmP.esm.js → share-button-BxrZs18u.esm.js} +2 -2
- package/dist/chunks/{share-button-DP2wLhmP.esm.js.map → share-button-BxrZs18u.esm.js.map} +1 -1
- package/dist/chunks/{share-button-CqrSfHAr.esm.js → share-button-DQT2zQ7w.esm.js} +3 -2
- package/dist/chunks/{share-button-CqrSfHAr.esm.js.map → share-button-DQT2zQ7w.esm.js.map} +1 -1
- package/dist/components/community-impact.esm.js +1 -1
- package/dist/components/community-impact.js +1 -1
- package/dist/components/cumulative-impact.esm.js +1 -1
- package/dist/components/cumulative-impact.js +1 -1
- package/dist/components/impact-overview.esm.js +1 -1
- package/dist/components/impact-overview.js +1 -1
- package/dist/components/index.esm.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/post-purchase.esm.js +1 -1
- package/dist/components/post-purchase.js +1 -1
- package/dist/components/product-details-page.esm.js +1 -1
- package/dist/components/product-details-page.js +1 -1
- package/dist/components/redeem-transaction.esm.js +1 -1
- package/dist/components/redeem-transaction.js +1 -1
- package/dist/components/select-nonprofit.esm.js +1 -1
- package/dist/components/select-nonprofit.js +1 -1
- package/dist/components/select-subscription-nonprofit.esm.js +1 -1
- package/dist/components/select-subscription-nonprofit.js +1 -1
- package/dist/components/shopify.esm.js +1 -1
- package/dist/components/shopify.js +1 -1
- package/dist/components/social-share.esm.js +1 -1
- package/dist/components/social-share.js +1 -1
- package/dist/components/subscriber-select-nonprofit.esm.js +1 -1
- package/dist/components/subscriber-select-nonprofit.js +1 -1
- package/dist/components/subscription-impact.d.ts +1 -0
- package/dist/components/subscription-impact.esm.js +18 -17
- package/dist/components/subscription-impact.esm.js.map +1 -1
- package/dist/components/subscription-impact.js +18 -17
- package/dist/components/subscription-impact.js.map +1 -1
- package/dist/components/subscription-management.d.ts +2 -0
- package/dist/components/subscription-management.esm.js +19 -17
- package/dist/components/subscription-management.esm.js.map +1 -1
- package/dist/components/subscription-management.js +19 -17
- package/dist/components/subscription-management.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/beam.esm.js +1 -1
- package/dist/integrations/beam.js +1 -1
- package/dist/integrations/cart.esm.js +1 -1
- package/dist/integrations/cart.js +1 -1
- package/dist/integrations/logs.esm.js +1 -1
- package/dist/integrations/logs.js +1 -1
- package/dist/integrations/shopify-order.esm.js +1 -1
- package/dist/integrations/shopify-order.js +1 -1
- package/dist/integrations/shopify.esm.js +1 -1
- package/dist/integrations/shopify.js +1 -1
- package/dist/integrations/statsig.esm.js +14 -14
- package/dist/integrations/statsig.esm.js.map +1 -1
- package/dist/integrations/statsig.js +14 -14
- package/dist/integrations/statsig.js.map +1 -1
- package/dist/react/community-impact.esm.js +1 -1
- package/dist/react/community-impact.js +1 -1
- package/dist/react/cumulative-impact.esm.js +1 -1
- package/dist/react/cumulative-impact.js +1 -1
- package/dist/react/impact-overview.esm.js +1 -1
- package/dist/react/impact-overview.js +1 -1
- package/dist/react/index.esm.js +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/post-purchase.esm.js +1 -1
- package/dist/react/post-purchase.js +1 -1
- package/dist/react/product-details-page.esm.js +1 -1
- package/dist/react/product-details-page.js +1 -1
- package/dist/react/redeem-transaction.esm.js +1 -1
- package/dist/react/redeem-transaction.js +1 -1
- package/dist/react/select-nonprofit.esm.js +1 -1
- package/dist/react/select-nonprofit.js +1 -1
- package/dist/react/select-subscription-nonprofit.esm.js +1 -1
- package/dist/react/select-subscription-nonprofit.js +1 -1
- package/dist/react/social-share.esm.js +1 -1
- package/dist/react/social-share.js +1 -1
- package/dist/react/subscriber-select-nonprofit.esm.js +1 -1
- package/dist/react/subscriber-select-nonprofit.js +1 -1
- package/dist/react/subscription-impact.esm.js +1 -1
- package/dist/react/subscription-impact.js +1 -1
- package/dist/react/subscription-management.esm.js +1 -1
- package/dist/react/subscription-management.js +1 -1
- package/package.json +3 -3
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as c,s as i}from"./vendor-DUOg5fL-.esm.js";import{q as t}from"./index-
|
|
2
|
-
//# sourceMappingURL=_share-dialog-dependencies-
|
|
1
|
+
import{r as c,s as i}from"./vendor-DUOg5fL-.esm.js";import{q as t}from"./index-BlaOItQr.esm.js";import"./lit-BEag9MFp.esm.js";import"./utils-ly9wMwUO.esm.js";import"./lodash-CrMU6wKg.esm.js";const s="https://sdk.beamimpact.com",a=`${s}/lib/shoelace/v${t["@shoelace-style/shoelace"]}`,o=`${s}/lib/lucide-static/v${t["lucide-static"]}`;if(c("lucide",{resolver:e=>`${o}/icons/${e}.svg`}),i(a),document&&!document.querySelector("link[data-beam-impact]")){const e=document.createElement("link");e.href=`${a}/themes/light.css`,e.rel="stylesheet",e.setAttribute("data-beam-impact","true"),document.head.appendChild(e)}
|
|
2
|
+
//# sourceMappingURL=_share-dialog-dependencies-C3oAeUgm.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_share-dialog-dependencies-
|
|
1
|
+
{"version":3,"file":"_share-dialog-dependencies-C3oAeUgm.esm.js","sources":["../../src/shared/shoelace-components.ts"],"sourcesContent":["/**\n * Shoelace is a utility library for web components like icons, dialogs, buttons, etc.\n * https://shoelace.style/\n */\n\nimport { setBasePath } from \"@shoelace-style/shoelace/dist/utilities/base-path.js\";\nimport { registerIconLibrary } from \"@shoelace-style/shoelace/dist/utilities/icon-library.js\";\nimport { dependencies } from \"../../package.json\";\n\nconst CDN_BASE = \"https://sdk.beamimpact.com\";\nconst SHOELACE_BASE = `${CDN_BASE}/lib/shoelace/v${dependencies[\"@shoelace-style/shoelace\"]}`;\nconst ICON_BASE = `${CDN_BASE}/lib/lucide-static/v${dependencies[\"lucide-static\"]}`;\n\nregisterIconLibrary(\"lucide\", {\n resolver: (name: string) => `${ICON_BASE}/icons/${name}.svg`,\n});\n\nsetBasePath(SHOELACE_BASE);\n\nif (document && !document.querySelector(\"link[data-beam-impact]\")) {\n const stylesheet = document.createElement(\"link\");\n stylesheet.href = `${SHOELACE_BASE}/themes/light.css`;\n stylesheet.rel = \"stylesheet\";\n stylesheet.setAttribute(\"data-beam-impact\", \"true\");\n document.head.appendChild(stylesheet);\n}\n"],"names":["CDN_BASE","SHOELACE_BASE","dependencies","ICON_BASE","registerIconLibrary","name","setBasePath","stylesheet"],"mappings":"+LASA,MAAMA,EAAW,6BACXC,EAAgB,GAAGD,CAAQ,kBAAkBE,EAAa,0BAA0B,CAAC,GACrFC,EAAY,GAAGH,CAAQ,uBAAuBE,EAAa,eAAe,CAAC,GAQjF,GANAE,EAAoB,SAAU,CAC5B,SAAWC,GAAiB,GAAGF,CAAS,UAAUE,CAAI,MACxD,CAAC,EAEDC,EAAYL,CAAa,EAErB,UAAY,CAAC,SAAS,cAAc,wBAAwB,EAAG,CACjE,MAAMM,EAAa,SAAS,cAAc,MAAM,EAChDA,EAAW,KAAO,GAAGN,CAAa,oBAClCM,EAAW,IAAM,aACjBA,EAAW,aAAa,mBAAoB,MAAM,EAClD,SAAS,KAAK,YAAYA,CAAU,CACtC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as k,i as x,b as R}from"./lodash-CrMU6wKg.esm.js";import{R as M,l as u,K as V,C as U,N as X,b as $,O as H,U as Q,B as Y,W as Z,M as tt,t as et,P as at,n as nt,V as ot,A as it,X as rt}from"./utils-ly9wMwUO.esm.js";import{g as E}from"../react/shopify.esm.js";import{B as P}from"./index-
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
import{o as k,i as x,b as R}from"./lodash-CrMU6wKg.esm.js";import{R as M,l as u,K as V,C as U,N as X,b as $,O as H,U as Q,B as Y,W as Z,M as tt,t as et,P as at,n as nt,V as ot,A as it,X as rt}from"./utils-ly9wMwUO.esm.js";import{g as E}from"../react/shopify.esm.js";import{B as P}from"./index-BlaOItQr.esm.js";import{O}from"./index-BhlTVL8_.esm.js";const A=window.Shopify?.routes?.root||"/";let C=null,L=!0,T=!1;const st="cart";async function W(t,c=!0){if(C)return!1;const s=new AbortController;C=s;const{signal:e}=s;$(),window.addEventListener(H.eventName,async()=>{T=!0},{signal:e}),window.addEventListener(Q.eventName,async a=>{const o=a,i=/cart\/(add|change|update|clear)/,r=o.detail.type==="xhr"?o.detail.xhr.responseURL:o.detail.response.url,n=new URL(r);if(!i.test(n.pathname))return;const p=await S(t,e);e.aborted||!p.changed||O(t,p.cart)},{signal:e});let d,l;window.addEventListener(Y.eventName,async a=>{const o=a;u.debug("[cart-page][BeamNonprofitSelectEvent]",o.detail);const{source:i,selectedNonprofitId:r,selectionId:n}=o.detail;if(i===Z.select_nonprofit){if(d===r&&l===n)return;const p=await g(t);await f({...p,selectedNonprofitId:r,selectionId:n}),l=n,d=r}},{signal:e}),window.addEventListener(tt.eventName,async a=>{const o=a;u.debug("[cart-page][BeamNonprofitSelectionRemovedEvent]",o.detail);const{newNonprofitId:i,selectionId:r}=o.detail;if(d===i&&l===r)return;const n=await g(t);await f({...n,selectedNonprofitId:null,selectionId:r}),l=r,d=i},{signal:e}),window.addEventListener(et.eventName,async a=>{const o=a;if(u.debug("[cart-page][BeamCartCreatedEvent]",o.detail),E()||c){const i=await g(t);await f(i)}},{signal:e}),window.addEventListener(at.eventName,async a=>{const o=a;if(u.debug("[cart-page][BeamCartChangeEvent]",o.detail),E()||c){const i=await g(t);await f(i)}},{signal:e});try{if(e.aborted)return!1;const a=await S(t,e);return!(e.aborted||(await O(t,a.cart,!0),e.aborted))}catch(a){return u.error(new nt("Failed to sync initial cart during registerCartIntegration",{cause:a})),!1}}async function D(t,{clearStorage:c=!1}={}){const s=!!C;return s&&(C?.abort(),C=null,rt(),f.reset(),J.reset(),L=!0,T=!1),c&&ot(t),s}async function j(t,c,s){const e={...await g(t),...c!==void 0&&{selectedNonprofitId:c},...s!==void 0&&{selectionId:s}};await f(e)}function F(){const t=E();return{showBeam:t?.showBeam,remoteSessionId:t?.stableId}}async function g(t){const{showBeam:c,remoteSessionId:s}=F(),e=V(st,t),d=U(P,t),{chainId:l,storeId:a}=t;return{showBeam:c,remoteSessionId:s,beamCartId:d&&d!=="null"?d:void 0,cartId:e&&e!=="null"?e:void 0,chainId:l,storeId:a}}const z=j;async function S(t,c){const{token:s,total_price:e,item_count:d,currency:l,items:a,cart_level_discount_applications:o,attributes:i}=await v();let r=!1;const n=it(t),p=n.getItemJson("cart"),_=U(P,t),y={cartId:s,beamCartId:_,subtotal:e/100,itemCount:d,currencyCode:l,schema:{source:"generic"},content:{items:a.map(({sku:m,final_line_price:w,product_id:N,line_level_discount_allocations:B})=>{const h=m||String(N),b=w/100,K=B?.map(({discount_application:q})=>({code:q?.title,applicable:!0}));return{remoteProductIdentifier:h,localAmount:b,discounts:K}}),discounts:o.map(({title:m})=>({code:m,applicable:!0}))}};let I=null;try{i?.beam&&(I=JSON.parse(i.beam))}catch(m){u.error(m)}if(I&&L&&!T&&!c?.aborted){L=!1;const{nonprofit_id:m,selection_id:w}=I,N=n.getItem("nonprofit"),B=n.getItem("transaction"),h=m!==void 0&&String(m)!==N,b=w!=null&&String(w)!==B;(h||b)&&(h&&(n.setItem("nonprofit",String(m)),n.setItem("nonprofit_selected_at",new Date().toISOString())),b&&(n.setItem("transaction",String(w)),n.setItem("nonprofit_selected_at",new Date().toISOString())),window.dispatchEvent(new X({nonprofitId:m,nonprofitIdChanged:h,selectionId:w,selectionIdChanged:b})))}return x(y,{...p,beamCartId:p?.beamCartId})||(r=!0),{changed:r,cart:y}}const G=O,v=async function(){return await window.fetch(A+"cart.js",{method:"GET",headers:{"Content-Type":"application/json"}}).then(t=>t.json())},f=M(async function({selectedNonprofitId:t,selectionId:c,beamCartId:s,cartId:e,chainId:d,storeId:l,showBeam:a,remoteSessionId:o}){const{attributes:i}=await v(),r=i?.beam;let n={};try{r&&(n=JSON.parse(r))}catch(I){u.error(I)}const p=k({nonprofit_id:t,selection_id:c,beam_cart_id:s,shopify_cart_id:e,chain_id:d,store_id:l,show_beam:a,remote_session_id:o},R),_={...n,...p};t===null&&(_.nonprofit_id=void 0);const y={beam:JSON.stringify(_)};if(!x(_,n))try{await window.fetch(A+"cart/update.js",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({attributes:y})})}catch(I){u.error(I)}}),J=M(async function({selectedNonprofitId:t,selectionId:c,beamCartId:s,cartId:e,chainId:d,storeId:l}){const{showBeam:a,remoteSessionId:o}=F(),i=k({nonprofit_id:t,selection_id:c,beam_cart_id:s,shopify_cart_id:e,chain_id:d,store_id:l,show_beam:a,remote_session_id:o},R);t===null&&(i.nonprofit_id=void 0);const r={beam:JSON.stringify(i)};try{await window.fetch(A+"cart/update.js",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({attributes:r})})}catch(n){u.error(n)}});var ct=Object.freeze({__proto__:null,addBeamAttributesToCart:J,appendBeamAttributesToCart:f,appendStatsigToShopifyCartAttributes:z,appendToShopifyCartBeamAttribute:j,getBeamAttributesForCart:g,getCurrentCart:S,getShopifyCart:v,registerCartIntegration:W,trackCart:G,unregisterCartIntegration:D});export{j as J,S as L,J as M,v as O,z as a,g as b,ct as i,D as o,f as p,W as r,G as s};
|
|
2
|
+
//# sourceMappingURL=index-B2GUlwwp.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-DnFFgYbT.esm.js","sources":["../../src/integrations/shopify/cart.ts"],"sourcesContent":["/* eslint-disable camelcase */\nimport isEqual from \"lodash-es/isEqual\";\nimport isUndefined from \"lodash-es/isUndefined\";\nimport omitBy from \"lodash-es/omitBy\";\nimport { clearBeamStorage, logger, memoizeLast } from \"../../utils\";\nimport { BeamError } from \"../../utils/beam-errors\";\nimport { initNetworkListeners, teardownNetworkListeners } from \"../../utils/network-listeners\";\nimport {\n BeamCartChangeEvent,\n BeamCartCreatedEvent,\n BeamNetworkCallEvent,\n BeamNonprofitSelectEvent,\n BeamNonprofitSelectionRemovedEvent,\n BeamWidgetInitialNonprofitSyncCancelEvent,\n BeamWidgetInitialNonprofitSyncEvent,\n} from \"../../utils/events\";\nimport { createScopedLocalStorage } from \"../../utils/local-storage\";\nimport { getBeamStatsigContext } from \"../../shared/beam-statsig-context\";\nimport { BEAM_CART_COOKIE_NAME, TBeamCartLocalStorage, TCart, TCartItems } from \"../../shared/cart-contents\";\nimport { BeamCartAPIConfig, updateCart } from \"../cart\";\nimport { WIDGET_NAMES } from \"../../api-sdk/constants\";\nimport { getBeamCartId, getExternalCartId } from \"../../utils/cart\";\n\nexport type BeamShopifyCartIntegrationConfig = BeamCartAPIConfig & {\n storeId: number; // will be added to cart custom_attributes, and used in cart API call\n chainId?: number; // will be added to cart custom_attributes\n};\n\ntype ShopifyDiscountApplication = {\n title: string;\n value: string;\n};\n\ntype ShopifyLineLevelDiscountAllocations = {\n amount?: string;\n discount_application: ShopifyDiscountApplication;\n};\n\ntype ShopifyCartBeamAttribute = {\n nonprofit_id?: number | null;\n selection_id?: string;\n beam_cart_id?: string;\n shopify_cart_id?: string;\n chain_id?: number;\n store_id?: number;\n show_beam?: boolean;\n remote_session_id?: string;\n};\n\nconst SHOPIFY_BASE_URL = window.Shopify?.routes?.root || \"/\"; // see window.d.ts\n\nlet cartIntegrationAbortController: AbortController | null = null; // Set when registration starts; aborting removes its listeners\n\nlet allowEmitInitialNonprofitSync = true; // Skip updating local storage if already run initially\nlet skipEmitInitialNonprofitSync = false; // Allow other processes to skip the nonprofit sync from cart attributes\n\nconst SHOPIFY_CART_COOKIE_NAME = \"cart\";\n\n/**\n * @main registerCartIntegration - set up event listeners to integrate Beam with Shopify cart\n * @return {boolean} returns true if NEW listeners were created, false if setup was already done\n */\nasync function registerCartIntegration(\n config: BeamShopifyCartIntegrationConfig,\n autoUpdateShopifyCartAttributes = true,\n) {\n if (cartIntegrationAbortController) {\n return false; // Do nothing if already registered, or a registration attempt is already in progress\n }\n\n // All listeners below are registered with this signal so that\n // unregisterCartIntegration can remove them all with a single abort()\n const abortController = new AbortController();\n cartIntegrationAbortController = abortController;\n const { signal } = abortController;\n\n // logger.debug(\"[cart-page][registerCartIntegration] initializing network listeners\");\n // Set up event listeners for AJAX events (idempotent; re-enables dispatching if previously torn down)\n initNetworkListeners();\n\n /**\n * Allow another component to cancel the loading & setting\n * of the Shopify cart selection (like if a selection is made before we've gotten the previous values)\n */\n window.addEventListener(\n BeamWidgetInitialNonprofitSyncCancelEvent.eventName,\n async () => {\n // logger.debug(\"[cart-page][BeamWidgetInitialNonprofitSyncCancelEvent]\");\n skipEmitInitialNonprofitSync = true;\n },\n { signal },\n );\n\n // When any network call happens, check if it's for the Shopify /cart AJAX Api.\n // If so, and the cart is updated, send the cart to Beam\n window.addEventListener(\n BeamNetworkCallEvent.eventName,\n async (_event: Event) => {\n const event = _event as BeamNetworkCallEvent;\n const cartChangePaths = /cart\\/(add|change|update|clear)/;\n // note: response urls below follow redirects\n const requestUrlStr = event.detail.type === \"xhr\" ? event.detail.xhr.responseURL : event.detail.response.url;\n const url = new URL(requestUrlStr);\n if (!cartChangePaths.test(url.pathname)) {\n return;\n }\n // logger.debug(\"[cart-page][BeamNetworkCallEvent] getting current cart\");\n const currentCart = await getCurrentCart(config, signal);\n // Recheck: unregister can't cancel an invocation already in flight\n if (signal.aborted || !currentCart.changed) {\n // logger.debug(`[cart-page][BeamNetworkCallEvent] cart has not changed from URL ${requestUrlStr}`, currentCart.cart);\n return;\n }\n // Send cart to Beam to update timestamp, which is used for cart abandonment / ROI calc\n // logger.debug(`[cart-page][BeamNetworkCallEvent] cart has changed from URL ${requestUrlStr}`, currentCart.cart);\n updateCart(config, currentCart.cart);\n },\n { signal },\n );\n\n // Listen to Beam's own events to integrate Beam data into Shopify order\n let lastNonprofitId: number | null | undefined;\n let lastSelectionId: string | null | undefined;\n window.addEventListener(\n BeamNonprofitSelectEvent.eventName,\n async (_event) => {\n const event = _event as BeamNonprofitSelectEvent;\n logger.debug(\"[cart-page][BeamNonprofitSelectEvent]\", event.detail);\n const { source, selectedNonprofitId, selectionId } = event.detail;\n\n // On nonprofit selection, we always write Beam's attributes\n // to the Shopify cart attributes\n if (source === WIDGET_NAMES.select_nonprofit) {\n // Skip update if nothing changed (can happen if widget is re-initialized and\n // emits event after cache restoration, i.e., on cart re-render).\n if (lastNonprofitId === selectedNonprofitId && lastSelectionId === selectionId) {\n return;\n }\n\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart({\n ...beamCartData,\n selectedNonprofitId,\n selectionId,\n });\n lastSelectionId = selectionId;\n lastNonprofitId = selectedNonprofitId;\n }\n },\n { signal },\n );\n\n /**\n * Upon removal of the selected nonprofit from the widget and local storage,\n * an event is emitted and that event is then used to update the cart attributes accordingly\n * This event listener updates the cart attributes based on the emitted event\n */\n window.addEventListener(\n BeamNonprofitSelectionRemovedEvent.eventName,\n async (_event) => {\n const event = _event as BeamNonprofitSelectionRemovedEvent;\n logger.debug(\"[cart-page][BeamNonprofitSelectionRemovedEvent]\", event.detail);\n const { newNonprofitId, selectionId } = event.detail;\n\n if (lastNonprofitId === newNonprofitId && lastSelectionId === selectionId) {\n return;\n }\n\n // On nonprofit deselection, we always write Beam's attributes\n // to the Shopify cart attributes\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart({\n ...beamCartData,\n selectedNonprofitId: null,\n selectionId,\n });\n lastSelectionId = selectionId;\n lastNonprofitId = newNonprofitId;\n },\n { signal },\n );\n\n /**\n * When a BeamCart is created, write beam metadata to the Shopify cart if\n * we need to capture it for Statsig or Extensibility\n */\n window.addEventListener(\n BeamCartCreatedEvent.eventName,\n async (_event: Event) => {\n const event = _event as BeamCartCreatedEvent;\n logger.debug(\"[cart-page][BeamCartCreatedEvent]\", event.detail);\n if (getBeamStatsigContext() || autoUpdateShopifyCartAttributes) {\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart(beamCartData);\n }\n },\n { signal },\n );\n\n /**\n * On any cart changes, write beam metadata to the Shopify cart if\n * we need to capture it for Statsig or Extensibility\n */\n window.addEventListener(\n BeamCartChangeEvent.eventName,\n async (_event: Event) => {\n const event = _event as BeamCartChangeEvent;\n logger.debug(\"[cart-page][BeamCartChangeEvent]\", event.detail);\n if (getBeamStatsigContext() || autoUpdateShopifyCartAttributes) {\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart(beamCartData);\n }\n },\n { signal },\n );\n\n try {\n // Handle full-page load, ie, first-time page load and reloads from form submit events\n // This creates a GET to /cart.js\n if (signal.aborted) {\n return false; // unregistered before we even started\n }\n const currentCart = await getCurrentCart(config, signal);\n if (signal.aborted) {\n return false; // unregistered while the GET was in flight\n }\n // logger.debug(\"[cart-page][registerCartIntegration] initial cart fetch result\", currentCart);\n await updateCart(config, currentCart.cart, true);\n if (signal.aborted) {\n return false; // unregistered while updateCart was in flight\n }\n\n return true;\n } catch (err) {\n // A transient failure here (e.g. a flaky mobile network) is only about the initial\n // cart snapshot — don't tear down the listeners registered above, or the integration\n // goes dark for the rest of the page session over what's often a one-off blip.\n logger.error(new BeamError(\"Failed to sync initial cart during registerCartIntegration\", { cause: err }));\n return false;\n }\n}\n\n/**\n * @main unregisterCartIntegration - tear down listeners set up by registerCartIntegration.\n * Pass { clearStorage: true } to also wipe Beam's localStorage/cookies in the same call\n * (clearBeamStorage from src/utils, which is also callable on its own — for cases that want\n * storage cleared without touching listeners, or independently of this integration entirely).\n * @return {boolean} true if this page load's listeners were torn down, false if\n * registerCartIntegration never ran this session (storage still clears if requested, either way)\n */\nasync function unregisterCartIntegration(\n config: BeamShopifyCartIntegrationConfig,\n { clearStorage = false }: { clearStorage?: boolean } = {},\n) {\n // Also covers an unregister call that arrives mid-registration, before this is set true\n const wasRegisteredThisSession = Boolean(cartIntegrationAbortController);\n\n if (wasRegisteredThisSession) {\n // 1. Remove ALL event listeners registered with this controller's signal\n cartIntegrationAbortController?.abort();\n cartIntegrationAbortController = null;\n\n // 2. Stop fetch/XHR hooks from dispatching (patches stay installed, just inert)\n teardownNetworkListeners();\n\n // 3. Drop memoized state so nothing stale survives a re-register\n appendBeamAttributesToCart.reset();\n addBeamAttributesToCart.reset();\n\n // 4. Reset module flags so a future opt-in can re-register cleanly\n allowEmitInitialNonprofitSync = true;\n skipEmitInitialNonprofitSync = false;\n }\n\n // 5. Optionally clear storage too. Runs regardless of wasRegisteredThisSession — that state\n // is persisted browser-side, not tied to whether a registration happened this page load.\n if (clearStorage) {\n clearBeamStorage(config);\n }\n\n return wasRegisteredThisSession;\n}\n\n/* ***************************************** HELPER FUNCTIONS *****************************************\n These may be used individually to integrate with carts if the registerCartIntegration\n script doesn't work for some reason.\n ****************************************************************************************************/\n\nasync function appendToShopifyCartBeamAttribute(\n config: BeamShopifyCartIntegrationConfig,\n selectedNonprofitId?: number | null,\n selectionId?: string,\n) {\n const beamCartData = await getBeamAttributesForCart(config);\n const beamCartAttr = {\n ...beamCartData,\n ...(selectedNonprofitId !== undefined && { selectedNonprofitId }),\n ...(selectionId !== undefined && { selectionId }),\n };\n await appendBeamAttributesToCart(beamCartAttr);\n}\n\n/**\n * Gets the shopper's test group and stable ID from the Statsig plugin.\n * Both are undefined when this page isn't running a Beam test.\n */\nfunction getStatsigCartFields(): { showBeam?: boolean; remoteSessionId?: string } {\n const context = getBeamStatsigContext();\n return {\n showBeam: context?.showBeam,\n remoteSessionId: context?.stableId,\n };\n}\n\n/**\n * Gathers the base Beam data needed for updating a Shopify cart's metadata\n */\nasync function getBeamAttributesForCart(config: BeamShopifyCartIntegrationConfig) {\n const { showBeam, remoteSessionId } = getStatsigCartFields();\n\n const cartId = getExternalCartId(SHOPIFY_CART_COOKIE_NAME, config);\n const beamCartId = getBeamCartId(BEAM_CART_COOKIE_NAME, config);\n const { chainId, storeId } = config;\n\n return {\n showBeam,\n remoteSessionId,\n beamCartId: beamCartId && beamCartId !== \"null\" ? beamCartId : undefined,\n cartId: cartId && cartId !== \"null\" ? cartId : undefined,\n chainId,\n storeId,\n };\n}\n\n/**\n * Adds Statsig data to a Shopify cart\n */\nconst appendStatsigToShopifyCartAttributes = appendToShopifyCartBeamAttribute;\n\n/**\n * Detects change in cart since last page load,\n * by calling GET /cart.js, and returns cart values.\n * Used for:\n * - Form-based carts where the page refreshes to modify cart instead of using AJAX calls\n * - Hydrogen/GraphQL based carts (needs to be integrated manually)\n */\nasync function getCurrentCart(\n config: BeamShopifyCartIntegrationConfig,\n signal?: AbortSignal,\n): Promise<{\n changed: boolean;\n cart: {\n cartId: string;\n subtotal: number;\n itemCount: number;\n currencyCode: string;\n } & TCart;\n}> {\n const {\n token, // equal to \"cart\" cookie\n total_price, // this is the pretax value, after discounts, and multiplied by 100 (integer from decimal)\n item_count,\n currency,\n items,\n cart_level_discount_applications,\n attributes,\n } = await getShopifyCart();\n\n let changed = false;\n\n const localStorage = createScopedLocalStorage(config);\n\n // The cart cache is used to detect changes after page refreshes / across tabs\n const cachedCart: TBeamCartLocalStorage | null = localStorage.getItemJson(\"cart\");\n // The Beam cart cookie is used to identify the cart across subdomains\n // Use explicit null if empty because API requires it\n const beamCartId: string | null = getBeamCartId(BEAM_CART_COOKIE_NAME, config);\n\n const cart = {\n cartId: token,\n beamCartId,\n subtotal: total_price / 100,\n itemCount: item_count,\n currencyCode: currency,\n schema: { source: \"generic\" } as const,\n content: {\n // pull out minimal fields from full line items\n items: (items as TCartItems).map(({ sku, final_line_price, product_id, line_level_discount_allocations }) => {\n const remoteProductIdentifier = sku || String(product_id);\n const localAmount = final_line_price / 100;\n const discounts = (line_level_discount_allocations as ShopifyLineLevelDiscountAllocations[])?.map(\n ({ discount_application }) => {\n return { code: discount_application?.title, applicable: true };\n },\n );\n return { remoteProductIdentifier, localAmount, discounts };\n }),\n discounts: (cart_level_discount_applications as ShopifyDiscountApplication[]).map(({ title }) => {\n return { code: title, applicable: true };\n }),\n },\n };\n\n let beamAttr: ShopifyCartBeamAttribute | null = null;\n\n try {\n if (attributes?.beam) {\n beamAttr = JSON.parse(attributes.beam);\n }\n } catch (err) {\n logger.error(err);\n }\n\n /**\n * Only attempt to emit BeamWidgetInitialNonprofitSyncEvent once\n * as soon as we see a \"beam\" attribute for the first time.\n * allowEmitInitialNonprofitSync is local to this file to keep this\n * from running more than once.\n * skipEmitInitialNonprofitSync is settable by an event listener\n * so other processes can stop this sync from happening.\n * signal is checked too, so a call from a since-torn-down registration doesn't consume\n * the one-shot flag on its behalf.\n */\n if (beamAttr && allowEmitInitialNonprofitSync && !skipEmitInitialNonprofitSync && !signal?.aborted) {\n allowEmitInitialNonprofitSync = false;\n\n const { nonprofit_id, selection_id } = beamAttr;\n\n const storedNonprofit = localStorage.getItem(\"nonprofit\");\n const storedSelection = localStorage.getItem(\"transaction\");\n\n const nonprofitChanged = nonprofit_id !== undefined && String(nonprofit_id) !== storedNonprofit;\n const selectionChanged = selection_id != null && String(selection_id) !== storedSelection;\n\n // Only dispatch if something changed, and if it's not skipped\n if (nonprofitChanged || selectionChanged) {\n if (nonprofitChanged) {\n localStorage.setItem(\"nonprofit\", String(nonprofit_id));\n localStorage.setItem(\"nonprofit_selected_at\", new Date().toISOString());\n }\n\n if (selectionChanged) {\n localStorage.setItem(\"transaction\", String(selection_id));\n localStorage.setItem(\"nonprofit_selected_at\", new Date().toISOString());\n }\n\n window.dispatchEvent(\n new BeamWidgetInitialNonprofitSyncEvent({\n nonprofitId: nonprofit_id,\n nonprofitIdChanged: nonprofitChanged,\n selectionId: selection_id,\n selectionIdChanged: selectionChanged,\n }),\n );\n }\n }\n\n if (\n !isEqual(cart, {\n ...cachedCart,\n beamCartId: cachedCart?.beamCartId,\n })\n ) {\n changed = true;\n }\n\n // logger.debug(\"[cart-page][getCurrentCart] has cart changed?\", changed, cart);\n\n return { changed, cart };\n}\n\n/**\n * trackCart - Backwards-compatible alias for updateCart\n */\nconst trackCart = updateCart;\n\n/**\n * Helper function to get the Shopify cart attributes\n */\nconst getShopifyCart = async function () {\n const cart = await window\n .fetch(SHOPIFY_BASE_URL + \"cart.js\", {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" },\n })\n .then((res) => res.json());\n return cart;\n};\n\n/**\n * Sends Beam data to Shopify to integrate with order as custom attributes.\n * Memoized so that calls with the same data as the previous don't create additional API calls to Shopify.\n * This will do an append, not a full overwrite of the attributes in the beam property\n */\nconst appendBeamAttributesToCart = memoizeLast(async function appendBeamAttributesToCart({\n selectedNonprofitId,\n selectionId,\n beamCartId,\n cartId,\n chainId,\n storeId,\n showBeam,\n remoteSessionId,\n}: {\n selectedNonprofitId?: number | null;\n selectionId?: string;\n beamCartId?: string;\n cartId?: string;\n chainId?: number;\n storeId?: number;\n showBeam?: boolean;\n remoteSessionId?: string;\n}) {\n // logger.debug(\"[cart-page][appendBeamAttributesToCart] fetching existing cart\");\n const { attributes } = await getShopifyCart();\n\n // Get only the Beam attribute, if it exists\n const existingBeamCartAttrString = attributes?.beam;\n let existingBeamCartAttr = {};\n try {\n if (existingBeamCartAttrString) {\n existingBeamCartAttr = JSON.parse(existingBeamCartAttrString);\n }\n } catch (err) {\n logger.error(err);\n }\n\n const newBeamAttrs = omitBy(\n {\n nonprofit_id: selectedNonprofitId,\n selection_id: selectionId,\n beam_cart_id: beamCartId,\n shopify_cart_id: cartId,\n chain_id: chainId,\n store_id: storeId,\n show_beam: showBeam,\n remote_session_id: remoteSessionId,\n },\n isUndefined,\n );\n\n const appendedBeamAttributes = {\n ...existingBeamCartAttr,\n ...newBeamAttrs,\n } as ShopifyCartBeamAttribute;\n\n // For the nonprofitId, if we specifically get a null value here,\n // we want to remove it from the cart attributes, not just write \"null\"\n if (selectedNonprofitId === null) {\n appendedBeamAttributes.nonprofit_id = undefined;\n }\n\n const beamCartAttrs = {\n beam: JSON.stringify(appendedBeamAttributes),\n };\n\n // If the attributes match, no reason to update the cart\n if (isEqual(appendedBeamAttributes, existingBeamCartAttr)) {\n // logger.debug(\"[cart-page][appendBeamAttributesToCart] cart attributes match, skipping update\");\n return;\n }\n\n try {\n // logger.debug(\"[cart-page][appendBeamAttributesToCart] updating Shopify cart\");\n await window.fetch(SHOPIFY_BASE_URL + \"cart/update.js\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ attributes: beamCartAttrs }),\n });\n } catch (err) {\n logger.error(err); // don't throw, allow later calls to continue\n }\n});\n\n/**\n * Sends Beam data to Shopify to integrate with order as custom attributes.\n * Memoized so that calls with the same data as the previous don't create additional API calls to Shopify.\n * This method force-updates the \"beam\" attribute with the values passed in\n */\nconst addBeamAttributesToCart = memoizeLast(async function addBeamAttributesToCart({\n selectedNonprofitId,\n selectionId,\n beamCartId,\n cartId,\n chainId,\n storeId,\n}: {\n selectedNonprofitId?: number | null;\n selectionId?: string;\n beamCartId?: string;\n cartId?: string;\n chainId?: number;\n storeId?: number;\n}) {\n const { showBeam, remoteSessionId } = getStatsigCartFields();\n\n const allBeamAttributes = omitBy(\n {\n nonprofit_id: selectedNonprofitId,\n selection_id: selectionId,\n beam_cart_id: beamCartId,\n shopify_cart_id: cartId,\n chain_id: chainId,\n store_id: storeId,\n show_beam: showBeam,\n remote_session_id: remoteSessionId,\n },\n isUndefined,\n ) as ShopifyCartBeamAttribute;\n\n // For the nonprofitId, if we specifically get a null value here,\n // we want to remove it from the cart attributes, not just write \"null\"\n if (selectedNonprofitId === null) {\n allBeamAttributes.nonprofit_id = undefined;\n }\n\n const beamCartAttrs = {\n beam: JSON.stringify(allBeamAttributes),\n };\n\n try {\n await window.fetch(SHOPIFY_BASE_URL + \"cart/update.js\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ attributes: beamCartAttrs }),\n });\n } catch (err) {\n logger.error(err); // don't throw, allow later calls to continue\n }\n});\n\ndeclare global {\n interface Window {\n Shopify?: any;\n }\n}\n\nexport {\n trackCart,\n getCurrentCart,\n addBeamAttributesToCart,\n unregisterCartIntegration,\n appendStatsigToShopifyCartAttributes,\n appendToShopifyCartBeamAttribute,\n registerCartIntegration,\n appendBeamAttributesToCart,\n getShopifyCart,\n getBeamAttributesForCart,\n};\n"],"names":["SHOPIFY_BASE_URL","cartIntegrationAbortController","allowEmitInitialNonprofitSync","skipEmitInitialNonprofitSync","SHOPIFY_CART_COOKIE_NAME","registerCartIntegration","config","autoUpdateShopifyCartAttributes","abortController","signal","initNetworkListeners","BeamWidgetInitialNonprofitSyncCancelEvent","BeamNetworkCallEvent","_event","event","cartChangePaths","requestUrlStr","url","currentCart","getCurrentCart","updateCart","lastNonprofitId","lastSelectionId","BeamNonprofitSelectEvent","logger","source","selectedNonprofitId","selectionId","WIDGET_NAMES","beamCartData","getBeamAttributesForCart","appendBeamAttributesToCart","BeamNonprofitSelectionRemovedEvent","newNonprofitId","BeamCartCreatedEvent","getBeamStatsigContext","BeamCartChangeEvent","err","BeamError","unregisterCartIntegration","clearStorage","wasRegisteredThisSession","teardownNetworkListeners","addBeamAttributesToCart","clearBeamStorage","appendToShopifyCartBeamAttribute","beamCartAttr","getStatsigCartFields","context","showBeam","remoteSessionId","cartId","getExternalCartId","beamCartId","getBeamCartId","BEAM_CART_COOKIE_NAME","chainId","storeId","appendStatsigToShopifyCartAttributes","token","total_price","item_count","currency","items","cart_level_discount_applications","attributes","getShopifyCart","changed","localStorage","createScopedLocalStorage","cachedCart","cart","sku","final_line_price","product_id","line_level_discount_allocations","remoteProductIdentifier","localAmount","discounts","discount_application","title","beamAttr","nonprofit_id","selection_id","storedNonprofit","storedSelection","nonprofitChanged","selectionChanged","BeamWidgetInitialNonprofitSyncEvent","isEqual","trackCart","res","memoizeLast","existingBeamCartAttrString","existingBeamCartAttr","newBeamAttrs","omitBy","isUndefined","appendedBeamAttributes","beamCartAttrs","allBeamAttributes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-B2GUlwwp.esm.js","sources":["../../src/integrations/shopify/cart.ts"],"sourcesContent":["/* eslint-disable camelcase */\nimport isEqual from \"lodash-es/isEqual\";\nimport isUndefined from \"lodash-es/isUndefined\";\nimport omitBy from \"lodash-es/omitBy\";\nimport { clearBeamStorage, logger, memoizeLast } from \"../../utils\";\nimport { BeamError } from \"../../utils/beam-errors\";\nimport { initNetworkListeners, teardownNetworkListeners } from \"../../utils/network-listeners\";\nimport {\n BeamCartChangeEvent,\n BeamCartCreatedEvent,\n BeamNetworkCallEvent,\n BeamNonprofitSelectEvent,\n BeamNonprofitSelectionRemovedEvent,\n BeamWidgetInitialNonprofitSyncCancelEvent,\n BeamWidgetInitialNonprofitSyncEvent,\n} from \"../../utils/events\";\nimport { createScopedLocalStorage } from \"../../utils/local-storage\";\nimport { getBeamStatsigContext } from \"../../shared/beam-statsig-context\";\nimport { BEAM_CART_COOKIE_NAME, TBeamCartLocalStorage, TCart, TCartItems } from \"../../shared/cart-contents\";\nimport { BeamCartAPIConfig, updateCart } from \"../cart\";\nimport { WIDGET_NAMES } from \"../../api-sdk/constants\";\nimport { getBeamCartId, getExternalCartId } from \"../../utils/cart\";\n\nexport type BeamShopifyCartIntegrationConfig = BeamCartAPIConfig & {\n storeId: number; // will be added to cart custom_attributes, and used in cart API call\n chainId?: number; // will be added to cart custom_attributes\n};\n\ntype ShopifyDiscountApplication = {\n title: string;\n value: string;\n};\n\ntype ShopifyLineLevelDiscountAllocations = {\n amount?: string;\n discount_application: ShopifyDiscountApplication;\n};\n\ntype ShopifyCartBeamAttribute = {\n nonprofit_id?: number | null;\n selection_id?: string;\n beam_cart_id?: string;\n shopify_cart_id?: string;\n chain_id?: number;\n store_id?: number;\n show_beam?: boolean;\n remote_session_id?: string;\n};\n\nconst SHOPIFY_BASE_URL = window.Shopify?.routes?.root || \"/\"; // see window.d.ts\n\nlet cartIntegrationAbortController: AbortController | null = null; // Set when registration starts; aborting removes its listeners\n\nlet allowEmitInitialNonprofitSync = true; // Skip updating local storage if already run initially\nlet skipEmitInitialNonprofitSync = false; // Allow other processes to skip the nonprofit sync from cart attributes\n\nconst SHOPIFY_CART_COOKIE_NAME = \"cart\";\n\n/**\n * @main registerCartIntegration - set up event listeners to integrate Beam with Shopify cart\n * @return {boolean} returns true if NEW listeners were created, false if setup was already done\n */\nasync function registerCartIntegration(\n config: BeamShopifyCartIntegrationConfig,\n autoUpdateShopifyCartAttributes = true,\n) {\n if (cartIntegrationAbortController) {\n return false; // Do nothing if already registered, or a registration attempt is already in progress\n }\n\n // All listeners below are registered with this signal so that\n // unregisterCartIntegration can remove them all with a single abort()\n const abortController = new AbortController();\n cartIntegrationAbortController = abortController;\n const { signal } = abortController;\n\n // logger.debug(\"[cart-page][registerCartIntegration] initializing network listeners\");\n // Set up event listeners for AJAX events (idempotent; re-enables dispatching if previously torn down)\n initNetworkListeners();\n\n /**\n * Allow another component to cancel the loading & setting\n * of the Shopify cart selection (like if a selection is made before we've gotten the previous values)\n */\n window.addEventListener(\n BeamWidgetInitialNonprofitSyncCancelEvent.eventName,\n async () => {\n // logger.debug(\"[cart-page][BeamWidgetInitialNonprofitSyncCancelEvent]\");\n skipEmitInitialNonprofitSync = true;\n },\n { signal },\n );\n\n // When any network call happens, check if it's for the Shopify /cart AJAX Api.\n // If so, and the cart is updated, send the cart to Beam\n window.addEventListener(\n BeamNetworkCallEvent.eventName,\n async (_event: Event) => {\n const event = _event as BeamNetworkCallEvent;\n const cartChangePaths = /cart\\/(add|change|update|clear)/;\n // note: response urls below follow redirects\n const requestUrlStr = event.detail.type === \"xhr\" ? event.detail.xhr.responseURL : event.detail.response.url;\n const url = new URL(requestUrlStr);\n if (!cartChangePaths.test(url.pathname)) {\n return;\n }\n // logger.debug(\"[cart-page][BeamNetworkCallEvent] getting current cart\");\n const currentCart = await getCurrentCart(config, signal);\n // Recheck: unregister can't cancel an invocation already in flight\n if (signal.aborted || !currentCart.changed) {\n // logger.debug(`[cart-page][BeamNetworkCallEvent] cart has not changed from URL ${requestUrlStr}`, currentCart.cart);\n return;\n }\n // Send cart to Beam to update timestamp, which is used for cart abandonment / ROI calc\n // logger.debug(`[cart-page][BeamNetworkCallEvent] cart has changed from URL ${requestUrlStr}`, currentCart.cart);\n updateCart(config, currentCart.cart);\n },\n { signal },\n );\n\n // Listen to Beam's own events to integrate Beam data into Shopify order\n let lastNonprofitId: number | null | undefined;\n let lastSelectionId: string | null | undefined;\n window.addEventListener(\n BeamNonprofitSelectEvent.eventName,\n async (_event) => {\n const event = _event as BeamNonprofitSelectEvent;\n logger.debug(\"[cart-page][BeamNonprofitSelectEvent]\", event.detail);\n const { source, selectedNonprofitId, selectionId } = event.detail;\n\n // On nonprofit selection, we always write Beam's attributes\n // to the Shopify cart attributes\n if (source === WIDGET_NAMES.select_nonprofit) {\n // Skip update if nothing changed (can happen if widget is re-initialized and\n // emits event after cache restoration, i.e., on cart re-render).\n if (lastNonprofitId === selectedNonprofitId && lastSelectionId === selectionId) {\n return;\n }\n\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart({\n ...beamCartData,\n selectedNonprofitId,\n selectionId,\n });\n lastSelectionId = selectionId;\n lastNonprofitId = selectedNonprofitId;\n }\n },\n { signal },\n );\n\n /**\n * Upon removal of the selected nonprofit from the widget and local storage,\n * an event is emitted and that event is then used to update the cart attributes accordingly\n * This event listener updates the cart attributes based on the emitted event\n */\n window.addEventListener(\n BeamNonprofitSelectionRemovedEvent.eventName,\n async (_event) => {\n const event = _event as BeamNonprofitSelectionRemovedEvent;\n logger.debug(\"[cart-page][BeamNonprofitSelectionRemovedEvent]\", event.detail);\n const { newNonprofitId, selectionId } = event.detail;\n\n if (lastNonprofitId === newNonprofitId && lastSelectionId === selectionId) {\n return;\n }\n\n // On nonprofit deselection, we always write Beam's attributes\n // to the Shopify cart attributes\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart({\n ...beamCartData,\n selectedNonprofitId: null,\n selectionId,\n });\n lastSelectionId = selectionId;\n lastNonprofitId = newNonprofitId;\n },\n { signal },\n );\n\n /**\n * When a BeamCart is created, write beam metadata to the Shopify cart if\n * we need to capture it for Statsig or Extensibility\n */\n window.addEventListener(\n BeamCartCreatedEvent.eventName,\n async (_event: Event) => {\n const event = _event as BeamCartCreatedEvent;\n logger.debug(\"[cart-page][BeamCartCreatedEvent]\", event.detail);\n if (getBeamStatsigContext() || autoUpdateShopifyCartAttributes) {\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart(beamCartData);\n }\n },\n { signal },\n );\n\n /**\n * On any cart changes, write beam metadata to the Shopify cart if\n * we need to capture it for Statsig or Extensibility\n */\n window.addEventListener(\n BeamCartChangeEvent.eventName,\n async (_event: Event) => {\n const event = _event as BeamCartChangeEvent;\n logger.debug(\"[cart-page][BeamCartChangeEvent]\", event.detail);\n if (getBeamStatsigContext() || autoUpdateShopifyCartAttributes) {\n const beamCartData = await getBeamAttributesForCart(config);\n await appendBeamAttributesToCart(beamCartData);\n }\n },\n { signal },\n );\n\n try {\n // Handle full-page load, ie, first-time page load and reloads from form submit events\n // This creates a GET to /cart.js\n if (signal.aborted) {\n return false; // unregistered before we even started\n }\n const currentCart = await getCurrentCart(config, signal);\n if (signal.aborted) {\n return false; // unregistered while the GET was in flight\n }\n // logger.debug(\"[cart-page][registerCartIntegration] initial cart fetch result\", currentCart);\n await updateCart(config, currentCart.cart, true);\n if (signal.aborted) {\n return false; // unregistered while updateCart was in flight\n }\n\n return true;\n } catch (err) {\n // A transient failure here (e.g. a flaky mobile network) is only about the initial\n // cart snapshot — don't tear down the listeners registered above, or the integration\n // goes dark for the rest of the page session over what's often a one-off blip.\n logger.error(new BeamError(\"Failed to sync initial cart during registerCartIntegration\", { cause: err }));\n return false;\n }\n}\n\n/**\n * @main unregisterCartIntegration - tear down listeners set up by registerCartIntegration.\n * Pass { clearStorage: true } to also wipe Beam's localStorage/cookies in the same call\n * (clearBeamStorage from src/utils, which is also callable on its own — for cases that want\n * storage cleared without touching listeners, or independently of this integration entirely).\n * @return {boolean} true if this page load's listeners were torn down, false if\n * registerCartIntegration never ran this session (storage still clears if requested, either way)\n */\nasync function unregisterCartIntegration(\n config: BeamShopifyCartIntegrationConfig,\n { clearStorage = false }: { clearStorage?: boolean } = {},\n) {\n // Also covers an unregister call that arrives mid-registration, before this is set true\n const wasRegisteredThisSession = Boolean(cartIntegrationAbortController);\n\n if (wasRegisteredThisSession) {\n // 1. Remove ALL event listeners registered with this controller's signal\n cartIntegrationAbortController?.abort();\n cartIntegrationAbortController = null;\n\n // 2. Stop fetch/XHR hooks from dispatching (patches stay installed, just inert)\n teardownNetworkListeners();\n\n // 3. Drop memoized state so nothing stale survives a re-register\n appendBeamAttributesToCart.reset();\n addBeamAttributesToCart.reset();\n\n // 4. Reset module flags so a future opt-in can re-register cleanly\n allowEmitInitialNonprofitSync = true;\n skipEmitInitialNonprofitSync = false;\n }\n\n // 5. Optionally clear storage too. Runs regardless of wasRegisteredThisSession — that state\n // is persisted browser-side, not tied to whether a registration happened this page load.\n if (clearStorage) {\n clearBeamStorage(config);\n }\n\n return wasRegisteredThisSession;\n}\n\n/* ***************************************** HELPER FUNCTIONS *****************************************\n These may be used individually to integrate with carts if the registerCartIntegration\n script doesn't work for some reason.\n ****************************************************************************************************/\n\nasync function appendToShopifyCartBeamAttribute(\n config: BeamShopifyCartIntegrationConfig,\n selectedNonprofitId?: number | null,\n selectionId?: string,\n) {\n const beamCartData = await getBeamAttributesForCart(config);\n const beamCartAttr = {\n ...beamCartData,\n ...(selectedNonprofitId !== undefined && { selectedNonprofitId }),\n ...(selectionId !== undefined && { selectionId }),\n };\n await appendBeamAttributesToCart(beamCartAttr);\n}\n\n/**\n * Gets the shopper's test group and stable ID from the Statsig plugin.\n * Both are undefined when this page isn't running a Beam test.\n */\nfunction getStatsigCartFields(): { showBeam?: boolean; remoteSessionId?: string } {\n const context = getBeamStatsigContext();\n return {\n showBeam: context?.showBeam,\n remoteSessionId: context?.stableId,\n };\n}\n\n/**\n * Gathers the base Beam data needed for updating a Shopify cart's metadata\n */\nasync function getBeamAttributesForCart(config: BeamShopifyCartIntegrationConfig) {\n const { showBeam, remoteSessionId } = getStatsigCartFields();\n\n const cartId = getExternalCartId(SHOPIFY_CART_COOKIE_NAME, config);\n const beamCartId = getBeamCartId(BEAM_CART_COOKIE_NAME, config);\n const { chainId, storeId } = config;\n\n return {\n showBeam,\n remoteSessionId,\n beamCartId: beamCartId && beamCartId !== \"null\" ? beamCartId : undefined,\n cartId: cartId && cartId !== \"null\" ? cartId : undefined,\n chainId,\n storeId,\n };\n}\n\n/**\n * Adds Statsig data to a Shopify cart\n */\nconst appendStatsigToShopifyCartAttributes = appendToShopifyCartBeamAttribute;\n\n/**\n * Detects change in cart since last page load,\n * by calling GET /cart.js, and returns cart values.\n * Used for:\n * - Form-based carts where the page refreshes to modify cart instead of using AJAX calls\n * - Hydrogen/GraphQL based carts (needs to be integrated manually)\n */\nasync function getCurrentCart(\n config: BeamShopifyCartIntegrationConfig,\n signal?: AbortSignal,\n): Promise<{\n changed: boolean;\n cart: {\n cartId: string;\n subtotal: number;\n itemCount: number;\n currencyCode: string;\n } & TCart;\n}> {\n const {\n token, // equal to \"cart\" cookie\n total_price, // this is the pretax value, after discounts, and multiplied by 100 (integer from decimal)\n item_count,\n currency,\n items,\n cart_level_discount_applications,\n attributes,\n } = await getShopifyCart();\n\n let changed = false;\n\n const localStorage = createScopedLocalStorage(config);\n\n // The cart cache is used to detect changes after page refreshes / across tabs\n const cachedCart: TBeamCartLocalStorage | null = localStorage.getItemJson(\"cart\");\n // The Beam cart cookie is used to identify the cart across subdomains\n // Use explicit null if empty because API requires it\n const beamCartId: string | null = getBeamCartId(BEAM_CART_COOKIE_NAME, config);\n\n const cart = {\n cartId: token,\n beamCartId,\n subtotal: total_price / 100,\n itemCount: item_count,\n currencyCode: currency,\n schema: { source: \"generic\" } as const,\n content: {\n // pull out minimal fields from full line items\n items: (items as TCartItems).map(({ sku, final_line_price, product_id, line_level_discount_allocations }) => {\n const remoteProductIdentifier = sku || String(product_id);\n const localAmount = final_line_price / 100;\n const discounts = (line_level_discount_allocations as ShopifyLineLevelDiscountAllocations[])?.map(\n ({ discount_application }) => {\n return { code: discount_application?.title, applicable: true };\n },\n );\n return { remoteProductIdentifier, localAmount, discounts };\n }),\n discounts: (cart_level_discount_applications as ShopifyDiscountApplication[]).map(({ title }) => {\n return { code: title, applicable: true };\n }),\n },\n };\n\n let beamAttr: ShopifyCartBeamAttribute | null = null;\n\n try {\n if (attributes?.beam) {\n beamAttr = JSON.parse(attributes.beam);\n }\n } catch (err) {\n logger.error(err);\n }\n\n /**\n * Only attempt to emit BeamWidgetInitialNonprofitSyncEvent once\n * as soon as we see a \"beam\" attribute for the first time.\n * allowEmitInitialNonprofitSync is local to this file to keep this\n * from running more than once.\n * skipEmitInitialNonprofitSync is settable by an event listener\n * so other processes can stop this sync from happening.\n * signal is checked too, so a call from a since-torn-down registration doesn't consume\n * the one-shot flag on its behalf.\n */\n if (beamAttr && allowEmitInitialNonprofitSync && !skipEmitInitialNonprofitSync && !signal?.aborted) {\n allowEmitInitialNonprofitSync = false;\n\n const { nonprofit_id, selection_id } = beamAttr;\n\n const storedNonprofit = localStorage.getItem(\"nonprofit\");\n const storedSelection = localStorage.getItem(\"transaction\");\n\n const nonprofitChanged = nonprofit_id !== undefined && String(nonprofit_id) !== storedNonprofit;\n const selectionChanged = selection_id != null && String(selection_id) !== storedSelection;\n\n // Only dispatch if something changed, and if it's not skipped\n if (nonprofitChanged || selectionChanged) {\n if (nonprofitChanged) {\n localStorage.setItem(\"nonprofit\", String(nonprofit_id));\n localStorage.setItem(\"nonprofit_selected_at\", new Date().toISOString());\n }\n\n if (selectionChanged) {\n localStorage.setItem(\"transaction\", String(selection_id));\n localStorage.setItem(\"nonprofit_selected_at\", new Date().toISOString());\n }\n\n window.dispatchEvent(\n new BeamWidgetInitialNonprofitSyncEvent({\n nonprofitId: nonprofit_id,\n nonprofitIdChanged: nonprofitChanged,\n selectionId: selection_id,\n selectionIdChanged: selectionChanged,\n }),\n );\n }\n }\n\n if (\n !isEqual(cart, {\n ...cachedCart,\n beamCartId: cachedCart?.beamCartId,\n })\n ) {\n changed = true;\n }\n\n // logger.debug(\"[cart-page][getCurrentCart] has cart changed?\", changed, cart);\n\n return { changed, cart };\n}\n\n/**\n * trackCart - Backwards-compatible alias for updateCart\n */\nconst trackCart = updateCart;\n\n/**\n * Helper function to get the Shopify cart attributes\n */\nconst getShopifyCart = async function () {\n const cart = await window\n .fetch(SHOPIFY_BASE_URL + \"cart.js\", {\n method: \"GET\",\n headers: { \"Content-Type\": \"application/json\" },\n })\n .then((res) => res.json());\n return cart;\n};\n\n/**\n * Sends Beam data to Shopify to integrate with order as custom attributes.\n * Memoized so that calls with the same data as the previous don't create additional API calls to Shopify.\n * This will do an append, not a full overwrite of the attributes in the beam property\n */\nconst appendBeamAttributesToCart = memoizeLast(async function appendBeamAttributesToCart({\n selectedNonprofitId,\n selectionId,\n beamCartId,\n cartId,\n chainId,\n storeId,\n showBeam,\n remoteSessionId,\n}: {\n selectedNonprofitId?: number | null;\n selectionId?: string;\n beamCartId?: string;\n cartId?: string;\n chainId?: number;\n storeId?: number;\n showBeam?: boolean;\n remoteSessionId?: string;\n}) {\n // logger.debug(\"[cart-page][appendBeamAttributesToCart] fetching existing cart\");\n const { attributes } = await getShopifyCart();\n\n // Get only the Beam attribute, if it exists\n const existingBeamCartAttrString = attributes?.beam;\n let existingBeamCartAttr = {};\n try {\n if (existingBeamCartAttrString) {\n existingBeamCartAttr = JSON.parse(existingBeamCartAttrString);\n }\n } catch (err) {\n logger.error(err);\n }\n\n const newBeamAttrs = omitBy(\n {\n nonprofit_id: selectedNonprofitId,\n selection_id: selectionId,\n beam_cart_id: beamCartId,\n shopify_cart_id: cartId,\n chain_id: chainId,\n store_id: storeId,\n show_beam: showBeam,\n remote_session_id: remoteSessionId,\n },\n isUndefined,\n );\n\n const appendedBeamAttributes = {\n ...existingBeamCartAttr,\n ...newBeamAttrs,\n } as ShopifyCartBeamAttribute;\n\n // For the nonprofitId, if we specifically get a null value here,\n // we want to remove it from the cart attributes, not just write \"null\"\n if (selectedNonprofitId === null) {\n appendedBeamAttributes.nonprofit_id = undefined;\n }\n\n const beamCartAttrs = {\n beam: JSON.stringify(appendedBeamAttributes),\n };\n\n // If the attributes match, no reason to update the cart\n if (isEqual(appendedBeamAttributes, existingBeamCartAttr)) {\n // logger.debug(\"[cart-page][appendBeamAttributesToCart] cart attributes match, skipping update\");\n return;\n }\n\n try {\n // logger.debug(\"[cart-page][appendBeamAttributesToCart] updating Shopify cart\");\n await window.fetch(SHOPIFY_BASE_URL + \"cart/update.js\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ attributes: beamCartAttrs }),\n });\n } catch (err) {\n logger.error(err); // don't throw, allow later calls to continue\n }\n});\n\n/**\n * Sends Beam data to Shopify to integrate with order as custom attributes.\n * Memoized so that calls with the same data as the previous don't create additional API calls to Shopify.\n * This method force-updates the \"beam\" attribute with the values passed in\n */\nconst addBeamAttributesToCart = memoizeLast(async function addBeamAttributesToCart({\n selectedNonprofitId,\n selectionId,\n beamCartId,\n cartId,\n chainId,\n storeId,\n}: {\n selectedNonprofitId?: number | null;\n selectionId?: string;\n beamCartId?: string;\n cartId?: string;\n chainId?: number;\n storeId?: number;\n}) {\n const { showBeam, remoteSessionId } = getStatsigCartFields();\n\n const allBeamAttributes = omitBy(\n {\n nonprofit_id: selectedNonprofitId,\n selection_id: selectionId,\n beam_cart_id: beamCartId,\n shopify_cart_id: cartId,\n chain_id: chainId,\n store_id: storeId,\n show_beam: showBeam,\n remote_session_id: remoteSessionId,\n },\n isUndefined,\n ) as ShopifyCartBeamAttribute;\n\n // For the nonprofitId, if we specifically get a null value here,\n // we want to remove it from the cart attributes, not just write \"null\"\n if (selectedNonprofitId === null) {\n allBeamAttributes.nonprofit_id = undefined;\n }\n\n const beamCartAttrs = {\n beam: JSON.stringify(allBeamAttributes),\n };\n\n try {\n await window.fetch(SHOPIFY_BASE_URL + \"cart/update.js\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ attributes: beamCartAttrs }),\n });\n } catch (err) {\n logger.error(err); // don't throw, allow later calls to continue\n }\n});\n\ndeclare global {\n interface Window {\n Shopify?: any;\n }\n}\n\nexport {\n trackCart,\n getCurrentCart,\n addBeamAttributesToCart,\n unregisterCartIntegration,\n appendStatsigToShopifyCartAttributes,\n appendToShopifyCartBeamAttribute,\n registerCartIntegration,\n appendBeamAttributesToCart,\n getShopifyCart,\n getBeamAttributesForCart,\n};\n"],"names":["SHOPIFY_BASE_URL","cartIntegrationAbortController","allowEmitInitialNonprofitSync","skipEmitInitialNonprofitSync","SHOPIFY_CART_COOKIE_NAME","registerCartIntegration","config","autoUpdateShopifyCartAttributes","abortController","signal","initNetworkListeners","BeamWidgetInitialNonprofitSyncCancelEvent","BeamNetworkCallEvent","_event","event","cartChangePaths","requestUrlStr","url","currentCart","getCurrentCart","updateCart","lastNonprofitId","lastSelectionId","BeamNonprofitSelectEvent","logger","source","selectedNonprofitId","selectionId","WIDGET_NAMES","beamCartData","getBeamAttributesForCart","appendBeamAttributesToCart","BeamNonprofitSelectionRemovedEvent","newNonprofitId","BeamCartCreatedEvent","getBeamStatsigContext","BeamCartChangeEvent","err","BeamError","unregisterCartIntegration","clearStorage","wasRegisteredThisSession","teardownNetworkListeners","addBeamAttributesToCart","clearBeamStorage","appendToShopifyCartBeamAttribute","beamCartAttr","getStatsigCartFields","context","showBeam","remoteSessionId","cartId","getExternalCartId","beamCartId","getBeamCartId","BEAM_CART_COOKIE_NAME","chainId","storeId","appendStatsigToShopifyCartAttributes","token","total_price","item_count","currency","items","cart_level_discount_applications","attributes","getShopifyCart","changed","localStorage","createScopedLocalStorage","cachedCart","cart","sku","final_line_price","product_id","line_level_discount_allocations","remoteProductIdentifier","localAmount","discounts","discount_application","title","beamAttr","nonprofit_id","selection_id","storedNonprofit","storedSelection","nonprofitChanged","selectionChanged","BeamWidgetInitialNonprofitSyncEvent","isEqual","trackCart","res","memoizeLast","existingBeamCartAttrString","existingBeamCartAttr","newBeamAttrs","omitBy","isUndefined","appendedBeamAttributes","beamCartAttrs","allBeamAttributes"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{d as g,i as B}from"./lodash-CrMU6wKg.esm.js";import{R as f,A as S,D as K,C as R,v as L,h as x,F as J,T as O,o as P,P as T,t as U,n as z}from"./utils-ly9wMwUO.esm.js";import{B as l,o as D}from"./index-
|
|
2
|
-
//# sourceMappingURL=index-
|
|
1
|
+
import{d as g,i as B}from"./lodash-CrMU6wKg.esm.js";import{R as f,A as S,D as K,C as R,v as L,h as x,F as J,T as O,o as P,P as T,t as U,n as z}from"./utils-ly9wMwUO.esm.js";import{B as l,o as D}from"./index-BlaOItQr.esm.js";const M=50,E=g(f(async function(e,n,w=!1){try{const t=S({apiKey:e.apiKey}),h=e.baseUrl??K,o=t.getItemJson("cart"),a=R(l,e),y=L(e)??void 0,{cartId:d,subtotal:i,itemCount:c,currencyCode:m,content:{items:C=[],discounts:u=[]}={},schema:p={source:"generic"}}=n,r={cartId:d,subtotal:i,itemCount:c,currencyCode:m,content:{items:C,discounts:u},schema:p,beamCartId:a};if(w&&!o&&n?.itemCount){t.setItemJson("cart",{...r,beamCartId:a});return}if(B(r,{...o,cartId:o?.cartId})||n.itemCount===0&&(!a||o?.itemCount===0)){t.setItemJson("cart",{...r,beamCartId:a});return}x((u??[]).map(_=>({value:_?.code})),e.apiKey),window.dispatchEvent(new J({source:O.cart_update}));const v=await D({baseUrl:h,headers:{authorization:`Api-Key ${e.apiKey}`},requestBody:{beamCartId:a,storeId:e.storeId,remoteSessionId:y,cartId:d,subtotal:i,itemCount:c,currencyCode:m}}),{beamCartId:s,expiresAt:I,beamCartCreated:A}=v;s&&I&&await P({name:l,domain:e.domain,value:s,path:"/",expires:new Date(I).getTime()}),t.setItemJson("cart",{...r,beamCartId:s});const b={schema:p,content:{items:C,discounts:u},subtotal:i,itemCount:c,currencyCode:m,cartId:d,beamCartId:s};window.dispatchEvent(new T(b)),A&&window.dispatchEvent(new U(b))}catch(t){throw new z("Could not update cart in Beam",{cause:t})}}),M,{leading:!0});var N=Object.freeze({__proto__:null,updateCart:E});export{E as O,N as i};
|
|
2
|
+
//# sourceMappingURL=index-BhlTVL8_.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-BhlTVL8_.esm.js","sources":["../../src/integrations/cart/update-cart.ts"],"sourcesContent":["import isEqual from \"lodash-es/isEqual\";\nimport { DEFAULT_BASE_URL, HELPER_NAMES } from \"../../api-sdk/constants\";\nimport { BeamBaseAPIConfig } from \"../../api-sdk/types\";\nimport { postCart } from \"../../api-sdk/v3/routes\";\nimport { debounce, memoizeLast } from \"../../utils\";\nimport { BeamError } from \"../../utils/beam-errors\";\nimport { BEAM_CART_COOKIE_NAME, TBeamCartLocalStorage, TCartApi } from \"../../shared/cart-contents\";\nimport { setCookieValue } from \"../../utils/cookies\";\nimport { BeamCartChangeEvent, BeamCartCreatedEvent, BeamWidgetStoredPromoCodesEvent } from \"../../utils/events\";\nimport { createScopedLocalStorage } from \"../../utils/local-storage\";\nimport { getRemoteSession } from \"../../utils/remote-session\";\nimport { getBeamCartId } from \"../../utils/cart\";\nimport { formatStoreAndReturnPromoCodes } from \"../../utils/promoManager\";\n\nexport type BeamCartAPIConfig = BeamBaseAPIConfig & {\n storeId: number;\n domain?: string; // Domain to set cookies on\n statsigExperiment?: string;\n};\n\nexport type BeamCartValues = {\n cartId?: string; // External (partner) cart ID\n itemCount?: number;\n subtotal?: number;\n currencyCode?: string;\n} & Partial<TCartApi>;\n\n/**\n * The debounce time in milliseconds for updating the cart - updateCart will delay until it hasn't been called for\n * this long before handling the last call.\n */\nconst UPDATE_CART_DEBOUNCE_MS = 50;\n\n/**\n * Sends cart information to Beam\n * Memoized based on previous arguments - if the objects are deep-equal, no update is made.\n * @side-effects Sets beam_cart cookie, set cart data in localstorage\n * @example\n * const BeamConfig = { apiKey: 'abc-123' }\n * const { beamCartId } = await updateCart(BeamConfig, { beamCartId, itemCount, subtotal, currencyCode })\n * */\nconst updateCart = debounce(\n memoizeLast(async function updateCart(\n config: BeamCartAPIConfig,\n cartValues: BeamCartValues,\n isFirstCartUpdateOnPageLoad = false,\n ) {\n try {\n const localStorage = createScopedLocalStorage({ apiKey: config.apiKey });\n const baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n\n // The cart cache is used to detect changes after page refreshes / across tabs\n const cachedCart: TBeamCartLocalStorage | null = localStorage.getItemJson(\"cart\");\n // The Beam cart cookie is used to identify the cart across subdomains\n // Use explicit null if empty because API requires it\n const beamCartId: string | null = getBeamCartId(BEAM_CART_COOKIE_NAME, config);\n // Remote session ID (ie, device ID from an A/B testing tool) will be linked to the cart\n const remoteSessionId: string | undefined = getRemoteSession(config) ?? undefined;\n\n const {\n cartId,\n subtotal,\n itemCount,\n currencyCode,\n content: { items = [], discounts = [] } = {},\n schema = { source: \"generic\" },\n } = cartValues;\n\n const cartWithDefaults = {\n cartId,\n subtotal,\n itemCount,\n currencyCode,\n content: { items, discounts },\n schema,\n beamCartId,\n };\n\n // If this is our first time calling \"updateCart\" on page load, and there is\n // no prior \"cachedCart\", and the current Platform cart is not empty,\n // we should assume that the cart has not been interacted with.\n // In this case, we want to cache the current cart, but not send it to Beam\n // so that the next time we call this method, it will compare to the existing\n // Platform cart\n if (isFirstCartUpdateOnPageLoad && !cachedCart && !!cartValues?.itemCount) {\n // logger.debug(\n // \"[update-cart] first attempt to update cart; no prior cart found, cart is not empty; skipping update to Beam\"\n // );\n localStorage.setItemJson(\"cart\", {\n ...cartWithDefaults,\n beamCartId: beamCartId,\n });\n\n return;\n }\n\n // Early return conditions. Skip sending cart to Beam if any apply:\n // 1. The cart has not changed\n // 2. Cart is empty, unless the cart was not empty before\n if (\n isEqual(cartWithDefaults, {\n ...cachedCart,\n cartId: cachedCart?.cartId /* make sure optional key is defined even if empty */,\n }) || // cart has not changed, OR\n (cartValues.itemCount === 0 && // nothing in current cart, AND\n (!beamCartId || cachedCart?.itemCount === 0)) // no/expired prev cart or prev cart was empty\n ) {\n // logger.debug(\"[update-cart] cart not changed\");\n // If the cart has not changed because the cart is empty now,\n // we still want to save that this changed happened in our cached cart\n // so the next update will compare against a current cart\n localStorage.setItemJson(\"cart\", {\n ...cartWithDefaults,\n beamCartId: beamCartId,\n });\n\n return;\n }\n\n formatStoreAndReturnPromoCodes(\n (discounts ?? []).map((discount) => ({ value: discount?.code })),\n config.apiKey,\n );\n window.dispatchEvent(new BeamWidgetStoredPromoCodesEvent({ source: HELPER_NAMES.cart_update }));\n // logger.debug(\"[update-cart] sending cart update request\");\n const response = await postCart({\n baseUrl,\n headers: {\n authorization: `Api-Key ${config.apiKey}`,\n },\n requestBody: {\n beamCartId, // backwards compat: explicitly sending null here is required to get initial beamCartId\n storeId: config.storeId,\n remoteSessionId,\n cartId,\n subtotal,\n itemCount,\n currencyCode,\n },\n });\n\n // Response will contain a new beamCartId if one was not provided, or old one expired\n const { beamCartId: newBeamCartId, expiresAt, beamCartCreated } = response;\n\n if (newBeamCartId && expiresAt) {\n await setCookieValue({\n name: BEAM_CART_COOKIE_NAME,\n domain: config.domain,\n value: newBeamCartId,\n path: \"/\",\n // If we don't set an expiration, the cookie will be cleared when the tab is closed\n expires: new Date(expiresAt).getTime(),\n });\n }\n\n localStorage.setItemJson(\"cart\", {\n ...cartWithDefaults,\n beamCartId: newBeamCartId,\n });\n\n const eventDetail = {\n schema: schema as any, // TS union type can't figure out what variant applies here\n content: {\n items: items as any,\n discounts: discounts as any,\n },\n subtotal,\n itemCount,\n currencyCode,\n cartId,\n beamCartId: newBeamCartId,\n };\n\n // emit change event on any create/update/delete of cart items\n window.dispatchEvent(new BeamCartChangeEvent(eventDetail));\n\n // emit created event only when the cart is new according to Beam\n if (beamCartCreated) {\n window.dispatchEvent(new BeamCartCreatedEvent(eventDetail));\n }\n } catch (err) {\n throw new BeamError(\"Could not update cart in Beam\", { cause: err });\n }\n }),\n UPDATE_CART_DEBOUNCE_MS,\n { leading: true }, // handle first call immediately but delay for more calls within debounce window\n);\n\nexport { updateCart };\n"],"names":["UPDATE_CART_DEBOUNCE_MS","updateCart","debounce","memoizeLast","config","cartValues","isFirstCartUpdateOnPageLoad","localStorage","createScopedLocalStorage","baseUrl","DEFAULT_BASE_URL","cachedCart","beamCartId","getBeamCartId","BEAM_CART_COOKIE_NAME","remoteSessionId","getRemoteSession","cartId","subtotal","itemCount","currencyCode","items","discounts","schema","cartWithDefaults","isEqual","formatStoreAndReturnPromoCodes","discount","BeamWidgetStoredPromoCodesEvent","HELPER_NAMES","response","postCart","newBeamCartId","expiresAt","beamCartCreated","setCookieValue","eventDetail","BeamCartChangeEvent","BeamCartCreatedEvent","err","BeamError"],"mappings":"sOA+BMA,EAA0B,GAU1BC,EAAaC,EACjBC,EAAY,eACVC,EACAC,EACAC,EAA8B,GAC9B,CACA,GAAI,CACF,MAAMC,EAAeC,EAAyB,CAAE,OAAQJ,EAAO,MAAO,CAAC,EACjEK,EAAUL,EAAO,SAAWM,EAG5BC,EAA2CJ,EAAa,YAAY,MAAM,EAG1EK,EAA4BC,EAAcC,EAAuBV,CAAM,EAEvEW,EAAsCC,EAAiBZ,CAAM,GAAK,OAElE,CACJ,OAAAa,EACA,SAAAC,EACA,UAAAC,EACA,aAAAC,EACA,QAAS,CAAE,MAAAC,EAAQ,CAAA,EAAI,UAAAC,EAAY,CAAA,CAAG,EAAI,CAAA,EAC1C,OAAAC,EAAS,CAAE,OAAQ,SAAU,CAC/B,EAAIlB,EAEEmB,EAAmB,CACvB,OAAAP,EACA,SAAAC,EACA,UAAAC,EACA,aAAAC,EACA,QAAS,CAAE,MAAAC,EAAO,UAAAC,CAAU,EAC5B,OAAAC,EACA,WAAAX,CACF,EAQA,GAAIN,GAA+B,CAACK,GAAgBN,GAAY,UAAW,CAIzEE,EAAa,YAAY,OAAQ,CAC/B,GAAGiB,EACH,WAAYZ,CACd,CAAC,EAED,MACF,CAKA,GACEa,EAAQD,EAAkB,CACxB,GAAGb,EACH,OAAQA,GAAY,MACtB,CAAC,GACAN,EAAW,YAAc,IACvB,CAACO,GAAcD,GAAY,YAAc,GAC5C,CAKAJ,EAAa,YAAY,OAAQ,CAC/B,GAAGiB,EACH,WAAYZ,CACd,CAAC,EAED,MACF,CAEAc,GACGJ,GAAa,CAAA,GAAI,IAAKK,IAAc,CAAE,MAAOA,GAAU,IAAK,EAAE,EAC/DvB,EAAO,MACT,EACA,OAAO,cAAc,IAAIwB,EAAgC,CAAE,OAAQC,EAAa,WAAY,CAAC,CAAC,EAE9F,MAAMC,EAAW,MAAMC,EAAS,CAC9B,QAAAtB,EACA,QAAS,CACP,cAAe,WAAWL,EAAO,MAAM,EACzC,EACA,YAAa,CACX,WAAAQ,EACA,QAASR,EAAO,QAChB,gBAAAW,EACA,OAAAE,EACA,SAAAC,EACA,UAAAC,EACA,aAAAC,CACF,CACF,CAAC,EAGK,CAAE,WAAYY,EAAe,UAAAC,EAAW,gBAAAC,CAAgB,EAAIJ,EAE9DE,GAAiBC,GACnB,MAAME,EAAe,CACnB,KAAMrB,EACN,OAAQV,EAAO,OACf,MAAO4B,EACP,KAAM,IAEN,QAAS,IAAI,KAAKC,CAAS,EAAE,QAAA,CAC/B,CAAC,EAGH1B,EAAa,YAAY,OAAQ,CAC/B,GAAGiB,EACH,WAAYQ,CACd,CAAC,EAED,MAAMI,EAAc,CAClB,OAAQb,EACR,QAAS,CACP,MAAOF,EACP,UAAWC,CACb,EACA,SAAAJ,EACA,UAAAC,EACA,aAAAC,EACA,OAAAH,EACA,WAAYe,CACd,EAGA,OAAO,cAAc,IAAIK,EAAoBD,CAAW,CAAC,EAGrDF,GACF,OAAO,cAAc,IAAII,EAAqBF,CAAW,CAAC,CAE9D,OAASG,EAAK,CACZ,MAAM,IAAIC,EAAU,gCAAiC,CAAE,MAAOD,CAAI,CAAC,CACrE,CACF,CAAC,EACDvC,EACA,CAAE,QAAS,EAAK,CAClB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{b as p,m as E}from"./lit-BEag9MFp.esm.js";import{n as y,l as f,a3 as g,D as N,R as A,Q as _,q as F,d as R}from"./utils-ly9wMwUO.esm.js";const k=t=>Object.entries(t).map(([e,s])=>`${e}: ${s};`).join(`
|
|
2
|
-
`);class D{constructor(e,s){this.data=null,this.loading=!1,this.error=null,(this.host=e).addController(this),this.asyncFn=s}async exec(...e){this.lastArgs=e,this.loading=!0,this.host.requestUpdate();try{this.data=await this.asyncFn(...e),this.error=null}catch(s){s instanceof Error&&(this.error=s,this.data=null)}return this.loading=!1,this.host.requestUpdate(),this.data}async retry(){return this.exec(...this.lastArgs||[])}hostDisconnected(){}}var $="1.58.
|
|
2
|
+
`);class D{constructor(e,s){this.data=null,this.loading=!1,this.error=null,(this.host=e).addController(this),this.asyncFn=s}async exec(...e){this.lastArgs=e,this.loading=!0,this.host.requestUpdate();try{this.data=await this.asyncFn(...e),this.error=null}catch(s){s instanceof Error&&(this.error=s,this.data=null)}return this.loading=!1,this.host.requestUpdate(),this.data}async retry(){return this.exec(...this.lastArgs||[])}hostDisconnected(){}}var $="1.58.2",L={"@shoelace-style/shoelace":"2.20.1","lucide-static":"0.292.0"};async function b(t,e){const s={method:"GET",...e,headers:{"Content-Type":"application/json",Accept:"application/json","X-Beam-Client":"WebSDK","X-Beam-Client-Version":$,...e?.headers},preflightContinue:!0,mode:e?.mode||"cors",body:e?.body!=null?e.body:void 0};let a;try{a=await fetch(t,s)}catch(n){const o=new y(`Network call failed (${s?.method.toUpperCase()} ${t})`);throw o.cause=n,f.error(o,t),o}let c,l;try{l=await a.text(),l&&(c=JSON.parse(l))}catch(n){let o=n;throw n instanceof SyntaxError&&(o=new g(a,c,`Response invalid. Expected JSON. Received: "${l}"`),o.cause=n),f.error(o),o}if(!a.ok){const n=new g(a,c,"Response was not OK");throw f.error(n),n}return c}const i=(t,e,s)=>({[t]:async function({headers:a={},baseUrl:c=N,apiRoot:l="/api/v3",pathParams:n={},queryParams:o={},requestBody:d,keepalive:h}){const m=Object.entries(n).reduce((C,[T,O])=>C.replace(`{${T}}`,O),t),r=JSON.parse(JSON.stringify(o)),u=new URLSearchParams(r).toString(),w=c+l+m+(u&&`?${u}`),x={headers:a,method:e,body:JSON.stringify(d),...h!==void 0&&{keepalive:h}};return b(w,x)}})[t];i("/chain/{chainId}/nonprofits","get");const M=i("/impact","get"),U=i("/chain/{chainId}/cumulativeImpact","get"),B=i("/selectNonprofit","post");i("/transaction","post"),i("/transaction/{transactionId}","put");const J=i("/cart","post"),W=A(i("/chain/findEligibleNonprofitsForCart","post")),j=i("/logs","post"),q=i("/experimentSession","post"),z=i("/subscriptions/updateSubscriptionNonprofit","post"),I=i("/subscriptions/findOrCreateSubscription","post"),H=i("/productDetailsPage","post"),S={errorTitle:"Beam encountered an error. Please try again.",retry:"Retry"},K=({error:t,retry:e})=>{let s=p``;if(t instanceof g){const a=JSON.stringify({status:t.response.status,statusText:t.response.statusText,url:t.response.url,body:t.body},null,4);s=p`
|
|
3
3
|
<p><b>Network Response:</b></p>
|
|
4
4
|
<p>${a}</p>
|
|
5
5
|
`}return t instanceof _&&(s=p`
|
|
@@ -28,4 +28,4 @@ import{b as p,m as E}from"./lit-BEag9MFp.esm.js";import{n as y,l as f,a3 as g,D
|
|
|
28
28
|
color: var(${r}-color, ${h});
|
|
29
29
|
letter-spacing: var(${r}-letterSpacing, ${m});
|
|
30
30
|
`)},Q=(t,e)=>{if(e.startsWith("{")&&!e.startsWith("{{"))try{const s=JSON.parse(e);return s[t]??s.en??e}catch{return f.error(new y("Failed to extract JSON translation from string"),e),e}return e},Y=t=>t.every(e=>e instanceof HTMLElement),Z=F.CART;async function v(t,e){const{apiKey:s,baseUrl:a}=t;try{await j({baseUrl:a||R,headers:{authorization:`Api-Key ${s}`},requestBody:{...e}})}catch(c){f.error("Failed to send log",c)}}var tt=Object.freeze({__proto__:null,sendLog:v});export{D as A,Z as B,G as _,Y as a,U as b,K as c,Q as d,V as e,k as f,M as g,W as h,tt as i,I as j,z as k,H as l,B as m,i as n,J as o,q as p,L as q,b as r,v as s,X as u,$ as v};
|
|
31
|
-
//# sourceMappingURL=index-
|
|
31
|
+
//# sourceMappingURL=index-BlaOItQr.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-tkscjKkq.esm.js","sources":["../../src/shared/fragments/css-variable-map.ts","../../src/shared/controllers/async-controller.ts","../../src/api-sdk/fetch-json.ts","../../src/api-sdk/make-openapi-method.ts","../../src/api-sdk/v3/routes.ts","../../src/shared/fragments/error-message-template.ts","../../src/shared/fragments/loading-template.ts","../../src/shared/fragments/custom-text.ts","../../src/shared/localize.ts","../../src/shared/is-all-html-elements.ts","../../src/shared/cart-contents.ts","../../src/integrations/logs/index.ts"],"sourcesContent":["export const _cssVariableMap = (variables: Record<string, string>) => {\n return Object.entries(variables)\n .map(([k, v]) => `${k}: ${v};`)\n .join(\"\\n\");\n};\n","import { ReactiveController, ReactiveControllerHost } from \"lit\";\n\ntype AsyncFunction = (...args: any[]) => Promise<any>;\n\n/**\n * Creates a declarative wrapper around async operations\n * @example\n * class MyElement extends LitElement {\n * private user = new AsyncController(\n * this,\n * async ({ id }) => get(url, { id }));\n *\n * async updated(changedProperties) {\n * if (changedProperties.has(\"userId\")) {\n * await this.user.exec({ id: this.userId })\n * }\n * }\n *\n * render() {\n * const { data, loading, error } = this.user;\n * if (loading) return html`Please wait...`\n * if (error) return html`Error! <button @click=${this.user.retry}>Reload</button>`;\n * return html`My name is: ${data.name}`\n * }\n * }\n */\nexport class AsyncController<TFn extends AsyncFunction> implements ReactiveController {\n public data: Awaited<ReturnType<TFn>> | null = null;\n public loading = false;\n public error: Error | null = null;\n\n private readonly host: ReactiveControllerHost;\n private readonly asyncFn: TFn;\n private lastArgs?: Parameters<TFn>;\n\n constructor(host: ReactiveControllerHost, asyncFn: TFn) {\n (this.host = host).addController(this);\n this.asyncFn = asyncFn;\n }\n\n public async exec(...args: Parameters<TFn>): Promise<ReturnType<TFn> | null> {\n this.lastArgs = args;\n this.loading = true;\n this.host.requestUpdate();\n try {\n // TODO: prevent race condition if later invocation returns before earlier\n this.data = await this.asyncFn(...args);\n this.error = null;\n } catch (err) {\n if (err instanceof Error) {\n this.error = err;\n this.data = null;\n }\n }\n this.loading = false;\n this.host.requestUpdate();\n return this.data;\n }\n\n public async retry() {\n return this.exec(...((this.lastArgs || []) as Parameters<TFn>));\n }\n\n hostDisconnected() {\n // TODO: cancel API calls\n }\n}\n","/**\n * Wrapper over window.fetch that expects/returns JSON\n */\nimport { BeamError, NetworkError } from \"../utils/beam-errors\";\nimport { logger } from \"../utils/logger\";\nimport { version as pkgVersion } from \"../../package.json\";\n\nexport async function fetchJson<T = unknown>(url: RequestInfo, options?: RequestInit): Promise<T> {\n const fetchOptions = {\n method: \"GET\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"X-Beam-Client\": \"WebSDK\",\n \"X-Beam-Client-Version\": pkgVersion,\n ...options?.headers,\n },\n preflightContinue: true,\n mode: options?.mode || \"cors\",\n body: options?.body != null ? options.body : undefined,\n };\n\n let response;\n try {\n response = await fetch(url, fetchOptions);\n // fetch can throw a TypeError if the server can't be reached, catch and log below\n } catch (err) {\n const error = new BeamError(`Network call failed (${fetchOptions?.method.toUpperCase()} ${url})`);\n error.cause = err;\n logger.error(error, url);\n throw error;\n }\n let body;\n let text;\n // This can throw a SyntaxError if response payload is malformed JSON\n try {\n text = await response.text();\n if (text) {\n // (response can be empty)\n body = JSON.parse(text);\n }\n } catch (err) {\n let error = err as Error;\n if (err instanceof SyntaxError) {\n error = new NetworkError(response, body, `Response invalid. Expected JSON. Received: \"${text}\"`);\n error.cause = err;\n }\n logger.error(error);\n throw error;\n }\n // Translate 4xx, 5xx status to runtime error\n if (!response.ok) {\n const error = new NetworkError(response, body, \"Response was not OK\");\n logger.error(error);\n throw error;\n }\n\n return body;\n}\n","import { DEFAULT_BASE_URL } from \"./constants\";\nimport { fetchJson } from \"./fetch-json\";\nimport { paths } from \"./openapi-spec\";\nimport { THttpMethod } from \"./types\";\n\nexport const makeOpenApiMethod = <\n TPathName extends keyof paths,\n TMethod extends keyof paths[TPathName],\n TStatusCode extends paths[TPathName][TMethod] extends { responses: any }\n ? keyof paths[TPathName][TMethod][\"responses\"]\n : never,\n>(\n pathName: TPathName,\n method: TMethod,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used as `typeof okHttpStatus` in type positions\n okHttpStatus: TStatusCode,\n) => {\n type TRouteSpec = paths[typeof pathName];\n type TRouteMethod = TRouteSpec[typeof method];\n type TParams = \"parameters\" extends keyof TRouteMethod ? TRouteMethod[\"parameters\"] : never;\n type TPathParams = TParams extends { path: any } ? TParams[\"path\"] : Record<string, never>;\n type TQueryParams = TParams extends { query: any } ? TParams[\"query\"] : Record<string, never>;\n type TRequestBody = TRouteMethod extends { requestBody: { content: { \"application/json\": any } } }\n ? TRouteMethod[\"requestBody\"][\"content\"][\"application/json\"]\n : never;\n type TAllResponses = TRouteMethod extends { responses: any } ? TRouteMethod[\"responses\"] : never;\n type TOkResponse = TAllResponses[typeof okHttpStatus] extends { content: { \"application/json\": any } }\n ? TAllResponses[typeof okHttpStatus][\"content\"][\"application/json\"]\n : never;\n const openApi = {\n [pathName]: async function ({\n headers = {},\n baseUrl = DEFAULT_BASE_URL,\n apiRoot = \"/api/v3\",\n pathParams = {},\n queryParams = {},\n requestBody,\n keepalive,\n }: {\n baseUrl?: string;\n apiRoot?: string;\n pathParams?: TPathParams;\n queryParams?: TQueryParams;\n requestBody?: TRequestBody;\n headers?: Record<string, string>;\n keepalive?: boolean;\n }) {\n const pathWithParams: string = Object.entries(pathParams).reduce((newPath: string, [k, v]) => {\n return newPath.replace(`{${k}}`, v as string);\n }, pathName as string);\n const cleanQueryParams = JSON.parse(JSON.stringify(queryParams));\n const search = new URLSearchParams(cleanQueryParams as unknown as Record<string, string>).toString();\n const url = baseUrl + apiRoot + pathWithParams + (search && `?${search}`);\n const options = {\n headers,\n method: method as THttpMethod,\n body: JSON.stringify(requestBody),\n ...(keepalive !== undefined && { keepalive }),\n };\n\n return fetchJson<TOkResponse>(url, options);\n },\n };\n\n // Use object to create function with dynamic name, for better stacktraces\n return openApi[pathName];\n};\n","import { makeOpenApiMethod } from \"../make-openapi-method\";\nimport { memoizeLast } from \"../../utils\";\n\nexport const getChainNonprofits = makeOpenApiMethod(\"/chain/{chainId}/nonprofits\", \"get\", 200);\n\nexport const getImpact = makeOpenApiMethod(\"/impact\", \"get\", 200);\n\nexport const getCumulativeImpact = makeOpenApiMethod(\"/chain/{chainId}/cumulativeImpact\", \"get\", 200);\n\nexport const postSelectNonprofit = makeOpenApiMethod(\"/selectNonprofit\", \"post\", 201);\n\nexport const postTransaction = makeOpenApiMethod(\"/transaction\", \"post\", 201);\n\nexport const putTransaction = makeOpenApiMethod(\"/transaction/{transactionId}\", \"put\", 204);\n\nexport const postCart = makeOpenApiMethod(\"/cart\", \"post\", 200);\n\nexport const postChainEligibleNonprofitsForCart = memoizeLast(\n makeOpenApiMethod(\"/chain/findEligibleNonprofitsForCart\", \"post\", 200),\n);\n\nexport const postLogs = makeOpenApiMethod(\"/logs\", \"post\", 200);\n\nexport const postExperimentSession = makeOpenApiMethod(\"/experimentSession\", \"post\", 200);\n\nexport const updateSubscription = makeOpenApiMethod(\"/subscriptions/updateSubscriptionNonprofit\", \"post\", 200);\n\nexport const postFindOrCreateSubscription = makeOpenApiMethod(\"/subscriptions/findOrCreateSubscription\", \"post\", 200);\n\nexport const postProductDetailsPage = makeOpenApiMethod(\"/productDetailsPage\", \"post\", 200);\n","import { html } from \"lit\";\nimport { MissingConfig, NetworkError } from \"../../utils/beam-errors\";\n\nconst strings = {\n errorTitle: `Beam encountered an error. Please try again.`,\n retry: `Retry`,\n};\n\nexport const _errorMessage = ({ error, retry }: { error: Error; retry?: (...args: never) => void }) => {\n let details = html``;\n if (error instanceof NetworkError) {\n const response = JSON.stringify(\n {\n status: error.response.status,\n statusText: error.response.statusText,\n url: error.response.url,\n body: error.body,\n },\n null,\n 4,\n );\n details = html`\n <p><b>Network Response:</b></p>\n <p>${response}</p>\n `;\n }\n if (error instanceof MissingConfig) {\n details = html`\n <p><b>Missing Required Config Options:</b></p>\n <p>${error.missingConfigKeyNames.join(\", \")}</p>\n `;\n }\n return html`<div class=\"beam-error\" style=\"text-align: left\">\n <p>${strings.errorTitle} ${retry ? html` <button type=\"reset\" @click=\"${retry}\">${strings.retry}</button>` : \"\"}</p>\n <br />\n <details>\n <div style=\"white-space: pre-wrap; font-family: monospace; line-height: 1;\">\n ${details}\n <p><b>Message:</b> ${error.message || html`<i>None</i>`}</p>\n <p><b>Stack:</b> ${error.stack}</p>\n </div>\n </details>\n <br />\n <p>Help: <a href=\"https://www.beamimpact.com\">www.beamimpact.com</a></p>\n </div>`;\n};\n","import { html } from \"lit\";\n\nconst strings = {\n loading: \"\", // Default is no loading content\n};\n\nexport const _loading = () => {\n return html`<p class=\"beam-loading\">${strings.loading}</p>`;\n};\n","import { CSSResult, unsafeCSS } from \"lit\";\n\n/**\n * Create an object that can be passed to cssVariableMap\n * to define CSS variables in a style tag. The default properties\n * are the ones exposed for customization in the remote config interface.\n * @example\n * const variables = {\n * ...customizableTextJs(\"widget-header\",\n * \"widget-border-color\": \"red\"\n * };\n *\n * html`<style>:host { ${_cssVariableMap(variables)} }</style>`;\n * @returns {{[p: string]: string}}\n */\nexport const defineCustomText = (\n namespace = \"\",\n {\n fontFamily = \"inherit\",\n fontStyle = \"inherit\",\n fontSize = \"inherit\",\n fontWeight = \"inherit\",\n textTransform = \"none\",\n textDecoration = \"none\",\n marginTop = \"0\",\n lineHeight = \"inherit\",\n color = \"inherit\",\n letterSpacing = \"normal\",\n } = {},\n): Record<string, string> => {\n const prefix = namespace.startsWith(\"--beam-\") ? namespace : `--beam-${namespace}`;\n return {\n [`${prefix}-fontFamily`]: fontFamily,\n [`${prefix}-fontStyle`]: fontStyle,\n [`${prefix}-fontSize`]: fontSize,\n [`${prefix}-fontWeight`]: fontWeight,\n [`${prefix}-textTransform`]: textTransform,\n [`${prefix}-marginTop`]: marginTop,\n [`${prefix}-lineHeight`]: lineHeight,\n [`${prefix}-color`]: color,\n [`${prefix}-letterSpacing`]: letterSpacing,\n [`${prefix}-textDecoration`]: textDecoration,\n };\n};\n\n/**\n * Returns a string that defines css properties based on variables,\n * which can be used in a css`` template. The default properties are the\n * ones exposed for customization in the remote config interface.\n * @example\n * css`.widget-header { ${customizableTextCss(\"widget-header\")} border: none; }`\n * @returns {CSSResult}\n */\nexport const useCustomText = (\n namespace = \"\",\n {\n fontFamily = \"inherit\",\n fontStyle = \"inherit\",\n fontSize = \"inherit\",\n fontWeight = \"inherit\",\n textTransform = \"none\",\n textDecoration = \"none\",\n marginTop = \"0\",\n lineHeight = \"inherit\",\n color = \"inherit\",\n letterSpacing = \"normal\",\n } = {},\n): CSSResult => {\n const prefix = namespace.startsWith(\"--beam-\") ? namespace : `--beam-${namespace}`;\n return unsafeCSS(`\\\n font-family: var(${prefix}-fontFamily, ${fontFamily});\n font-style: var(${prefix}-fontStyle, ${fontStyle});\n font-size: var(${prefix}-fontSize, ${fontSize});\n font-weight: var(${prefix}-fontWeight, ${fontWeight});\n text-transform: var(${prefix}-textTransform, ${textTransform});\n margin-top: var(${prefix}-marginTop, ${marginTop});\n line-height: var(${prefix}-lineHeight, ${lineHeight});\n text-decoration: var(${prefix}-textDecoration, ${textDecoration});\n color: var(${prefix}-color, ${color});\n letter-spacing: var(${prefix}-letterSpacing, ${letterSpacing});\n `);\n};\n\n/**\n * Same as useCustomText except returns an object that can be passed to styleMap\n */\nexport const useCustomTextMap = (\n namespace = \"\",\n {\n fontSize = \"inherit\",\n fontStyle = \"inherit\",\n fontWeight = \"inherit\",\n textTransform = \"none\",\n textDecoration = \"none\",\n marginTop = \"0\",\n lineHeight = \"inherit\",\n letterSpacing = \"normal\",\n } = {},\n): Record<string, string> => {\n const prefix = namespace.startsWith(\"--beam-\") ? namespace : `--beam-${namespace}`;\n return {\n fontSize: `var(${prefix}-fontSize, ${fontSize})`,\n fontStyle: `var(${prefix}-fontStyle, ${fontStyle})`,\n fontWeight: `var(${prefix}-fontWeight, ${fontWeight})`,\n textTransform: `var(${prefix}-textTransform, ${textTransform})`,\n textDecoration: `var(${prefix}-textDecoration, ${textDecoration})`,\n marginTop: `var(${prefix}-marginTop, ${marginTop})`,\n lineHeight: `var(${prefix}-lineHeight, ${lineHeight})`,\n letterSpacing: `var(${prefix}-letterSpacing, ${letterSpacing})`,\n };\n};\n","import { LANGUAGES } from \"../api-sdk/types\";\nimport { logger } from \"../utils/logger\";\nimport { BeamError } from \"../utils/beam-errors\";\n\n/**\n * User-provided strings may include embedded translations in JSON form\n * This function extracts the string for the provided language\n * If it fails to parse, or the string is not json-like, it returns the whole string\n */\nconst localizeUserString = (lang: LANGUAGES, str: string): string => {\n const isJson = str.startsWith(\"{\") && !str.startsWith(\"{{\");\n if (isJson) {\n try {\n const json = JSON.parse(str);\n return json[lang] ?? json[\"en\"] ?? str;\n } catch (err) {\n logger.error(new BeamError(\"Failed to extract JSON translation from string\"), str);\n return str;\n }\n }\n return str;\n};\n\nexport { localizeUserString };\n","export const isAllHtmlElements = (a: Array<unknown>): a is Array<HTMLElement> => {\n return a.every((el) => el instanceof HTMLElement);\n};\n","import { paths } from \"../api-sdk/openapi-spec\";\nimport { BEAM_COOKIE_NAMES } from \"../api-sdk/constants\";\nexport type TCartApi =\n paths[\"/chain/findEligibleNonprofitsForCart\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"cart\"];\n\n// Same as type from API but with non-optional fields, so we can use where Shopify guarantees values\nexport type TCart = TCartApi & {\n content: {\n items: Record<string, any>[];\n discounts?: Record<string, any>[] | undefined | null;\n };\n};\n\nexport type TCartItems = TCart[\"content\"][\"items\"];\n\nexport type TCartDiscounts = TCart[\"content\"][\"discounts\"];\n\nexport type TBeamCartLocalStorage = {\n cartId: string;\n beamCartId?: string;\n subtotal: number;\n itemCount: number;\n currencyCode: string;\n} & TCart;\n\nexport const BEAM_CART_COOKIE_NAME = BEAM_COOKIE_NAMES.CART;\n\nexport type Discount = {\n code: string;\n applicable: boolean;\n};\n","import { postLogs } from \"../../api-sdk/v3/routes\";\nimport { logger } from \"../../utils/logger\";\nimport { DEFAULT_LOG_URL } from \"../../api-sdk/constants\";\nimport { paths } from \"../../api-sdk/openapi-spec\";\n\ntype PostLogsReq = paths[\"/logs\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\n\ninterface SendLogConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport async function sendLog(config: SendLogConfig, payload: PostLogsReq): Promise<void> {\n const { apiKey, baseUrl } = config;\n try {\n await postLogs({\n baseUrl: baseUrl || DEFAULT_LOG_URL,\n headers: {\n authorization: `Api-Key ${apiKey}`,\n },\n requestBody: {\n ...payload,\n },\n });\n } catch (err) {\n logger.error(\"Failed to send log\", err);\n }\n}\n"],"names":["_cssVariableMap","variables","k","v","AsyncController","host","asyncFn","args","err","fetchJson","url","options","fetchOptions","pkgVersion","response","error","BeamError","logger","body","text","NetworkError","makeOpenApiMethod","pathName","method","okHttpStatus","headers","baseUrl","DEFAULT_BASE_URL","apiRoot","pathParams","queryParams","requestBody","keepalive","pathWithParams","newPath","cleanQueryParams","search","getImpact","getCumulativeImpact","postSelectNonprofit","postCart","postChainEligibleNonprofitsForCart","memoizeLast","postLogs","postExperimentSession","updateSubscription","postFindOrCreateSubscription","postProductDetailsPage","strings","_errorMessage","retry","details","html","MissingConfig","_loading","defineCustomText","namespace","fontFamily","fontStyle","fontSize","fontWeight","textTransform","textDecoration","marginTop","lineHeight","color","letterSpacing","prefix","useCustomText","unsafeCSS","localizeUserString","lang","str","json","isAllHtmlElements","a","el","BEAM_CART_COOKIE_NAME","BEAM_COOKIE_NAMES","sendLog","config","payload","apiKey","DEFAULT_LOG_URL"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index-BlaOItQr.esm.js","sources":["../../src/shared/fragments/css-variable-map.ts","../../src/shared/controllers/async-controller.ts","../../src/api-sdk/fetch-json.ts","../../src/api-sdk/make-openapi-method.ts","../../src/api-sdk/v3/routes.ts","../../src/shared/fragments/error-message-template.ts","../../src/shared/fragments/loading-template.ts","../../src/shared/fragments/custom-text.ts","../../src/shared/localize.ts","../../src/shared/is-all-html-elements.ts","../../src/shared/cart-contents.ts","../../src/integrations/logs/index.ts"],"sourcesContent":["export const _cssVariableMap = (variables: Record<string, string>) => {\n return Object.entries(variables)\n .map(([k, v]) => `${k}: ${v};`)\n .join(\"\\n\");\n};\n","import { ReactiveController, ReactiveControllerHost } from \"lit\";\n\ntype AsyncFunction = (...args: any[]) => Promise<any>;\n\n/**\n * Creates a declarative wrapper around async operations\n * @example\n * class MyElement extends LitElement {\n * private user = new AsyncController(\n * this,\n * async ({ id }) => get(url, { id }));\n *\n * async updated(changedProperties) {\n * if (changedProperties.has(\"userId\")) {\n * await this.user.exec({ id: this.userId })\n * }\n * }\n *\n * render() {\n * const { data, loading, error } = this.user;\n * if (loading) return html`Please wait...`\n * if (error) return html`Error! <button @click=${this.user.retry}>Reload</button>`;\n * return html`My name is: ${data.name}`\n * }\n * }\n */\nexport class AsyncController<TFn extends AsyncFunction> implements ReactiveController {\n public data: Awaited<ReturnType<TFn>> | null = null;\n public loading = false;\n public error: Error | null = null;\n\n private readonly host: ReactiveControllerHost;\n private readonly asyncFn: TFn;\n private lastArgs?: Parameters<TFn>;\n\n constructor(host: ReactiveControllerHost, asyncFn: TFn) {\n (this.host = host).addController(this);\n this.asyncFn = asyncFn;\n }\n\n public async exec(...args: Parameters<TFn>): Promise<ReturnType<TFn> | null> {\n this.lastArgs = args;\n this.loading = true;\n this.host.requestUpdate();\n try {\n // TODO: prevent race condition if later invocation returns before earlier\n this.data = await this.asyncFn(...args);\n this.error = null;\n } catch (err) {\n if (err instanceof Error) {\n this.error = err;\n this.data = null;\n }\n }\n this.loading = false;\n this.host.requestUpdate();\n return this.data;\n }\n\n public async retry() {\n return this.exec(...((this.lastArgs || []) as Parameters<TFn>));\n }\n\n hostDisconnected() {\n // TODO: cancel API calls\n }\n}\n","/**\n * Wrapper over window.fetch that expects/returns JSON\n */\nimport { BeamError, NetworkError } from \"../utils/beam-errors\";\nimport { logger } from \"../utils/logger\";\nimport { version as pkgVersion } from \"../../package.json\";\n\nexport async function fetchJson<T = unknown>(url: RequestInfo, options?: RequestInit): Promise<T> {\n const fetchOptions = {\n method: \"GET\",\n ...options,\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n \"X-Beam-Client\": \"WebSDK\",\n \"X-Beam-Client-Version\": pkgVersion,\n ...options?.headers,\n },\n preflightContinue: true,\n mode: options?.mode || \"cors\",\n body: options?.body != null ? options.body : undefined,\n };\n\n let response;\n try {\n response = await fetch(url, fetchOptions);\n // fetch can throw a TypeError if the server can't be reached, catch and log below\n } catch (err) {\n const error = new BeamError(`Network call failed (${fetchOptions?.method.toUpperCase()} ${url})`);\n error.cause = err;\n logger.error(error, url);\n throw error;\n }\n let body;\n let text;\n // This can throw a SyntaxError if response payload is malformed JSON\n try {\n text = await response.text();\n if (text) {\n // (response can be empty)\n body = JSON.parse(text);\n }\n } catch (err) {\n let error = err as Error;\n if (err instanceof SyntaxError) {\n error = new NetworkError(response, body, `Response invalid. Expected JSON. Received: \"${text}\"`);\n error.cause = err;\n }\n logger.error(error);\n throw error;\n }\n // Translate 4xx, 5xx status to runtime error\n if (!response.ok) {\n const error = new NetworkError(response, body, \"Response was not OK\");\n logger.error(error);\n throw error;\n }\n\n return body;\n}\n","import { DEFAULT_BASE_URL } from \"./constants\";\nimport { fetchJson } from \"./fetch-json\";\nimport { paths } from \"./openapi-spec\";\nimport { THttpMethod } from \"./types\";\n\nexport const makeOpenApiMethod = <\n TPathName extends keyof paths,\n TMethod extends keyof paths[TPathName],\n TStatusCode extends paths[TPathName][TMethod] extends { responses: any }\n ? keyof paths[TPathName][TMethod][\"responses\"]\n : never,\n>(\n pathName: TPathName,\n method: TMethod,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- used as `typeof okHttpStatus` in type positions\n okHttpStatus: TStatusCode,\n) => {\n type TRouteSpec = paths[typeof pathName];\n type TRouteMethod = TRouteSpec[typeof method];\n type TParams = \"parameters\" extends keyof TRouteMethod ? TRouteMethod[\"parameters\"] : never;\n type TPathParams = TParams extends { path: any } ? TParams[\"path\"] : Record<string, never>;\n type TQueryParams = TParams extends { query: any } ? TParams[\"query\"] : Record<string, never>;\n type TRequestBody = TRouteMethod extends { requestBody: { content: { \"application/json\": any } } }\n ? TRouteMethod[\"requestBody\"][\"content\"][\"application/json\"]\n : never;\n type TAllResponses = TRouteMethod extends { responses: any } ? TRouteMethod[\"responses\"] : never;\n type TOkResponse = TAllResponses[typeof okHttpStatus] extends { content: { \"application/json\": any } }\n ? TAllResponses[typeof okHttpStatus][\"content\"][\"application/json\"]\n : never;\n const openApi = {\n [pathName]: async function ({\n headers = {},\n baseUrl = DEFAULT_BASE_URL,\n apiRoot = \"/api/v3\",\n pathParams = {},\n queryParams = {},\n requestBody,\n keepalive,\n }: {\n baseUrl?: string;\n apiRoot?: string;\n pathParams?: TPathParams;\n queryParams?: TQueryParams;\n requestBody?: TRequestBody;\n headers?: Record<string, string>;\n keepalive?: boolean;\n }) {\n const pathWithParams: string = Object.entries(pathParams).reduce((newPath: string, [k, v]) => {\n return newPath.replace(`{${k}}`, v as string);\n }, pathName as string);\n const cleanQueryParams = JSON.parse(JSON.stringify(queryParams));\n const search = new URLSearchParams(cleanQueryParams as unknown as Record<string, string>).toString();\n const url = baseUrl + apiRoot + pathWithParams + (search && `?${search}`);\n const options = {\n headers,\n method: method as THttpMethod,\n body: JSON.stringify(requestBody),\n ...(keepalive !== undefined && { keepalive }),\n };\n\n return fetchJson<TOkResponse>(url, options);\n },\n };\n\n // Use object to create function with dynamic name, for better stacktraces\n return openApi[pathName];\n};\n","import { makeOpenApiMethod } from \"../make-openapi-method\";\nimport { memoizeLast } from \"../../utils\";\n\nexport const getChainNonprofits = makeOpenApiMethod(\"/chain/{chainId}/nonprofits\", \"get\", 200);\n\nexport const getImpact = makeOpenApiMethod(\"/impact\", \"get\", 200);\n\nexport const getCumulativeImpact = makeOpenApiMethod(\"/chain/{chainId}/cumulativeImpact\", \"get\", 200);\n\nexport const postSelectNonprofit = makeOpenApiMethod(\"/selectNonprofit\", \"post\", 201);\n\nexport const postTransaction = makeOpenApiMethod(\"/transaction\", \"post\", 201);\n\nexport const putTransaction = makeOpenApiMethod(\"/transaction/{transactionId}\", \"put\", 204);\n\nexport const postCart = makeOpenApiMethod(\"/cart\", \"post\", 200);\n\nexport const postChainEligibleNonprofitsForCart = memoizeLast(\n makeOpenApiMethod(\"/chain/findEligibleNonprofitsForCart\", \"post\", 200),\n);\n\nexport const postLogs = makeOpenApiMethod(\"/logs\", \"post\", 200);\n\nexport const postExperimentSession = makeOpenApiMethod(\"/experimentSession\", \"post\", 200);\n\nexport const updateSubscription = makeOpenApiMethod(\"/subscriptions/updateSubscriptionNonprofit\", \"post\", 200);\n\nexport const postFindOrCreateSubscription = makeOpenApiMethod(\"/subscriptions/findOrCreateSubscription\", \"post\", 200);\n\nexport const postProductDetailsPage = makeOpenApiMethod(\"/productDetailsPage\", \"post\", 200);\n","import { html } from \"lit\";\nimport { MissingConfig, NetworkError } from \"../../utils/beam-errors\";\n\nconst strings = {\n errorTitle: `Beam encountered an error. Please try again.`,\n retry: `Retry`,\n};\n\nexport const _errorMessage = ({ error, retry }: { error: Error; retry?: (...args: never) => void }) => {\n let details = html``;\n if (error instanceof NetworkError) {\n const response = JSON.stringify(\n {\n status: error.response.status,\n statusText: error.response.statusText,\n url: error.response.url,\n body: error.body,\n },\n null,\n 4,\n );\n details = html`\n <p><b>Network Response:</b></p>\n <p>${response}</p>\n `;\n }\n if (error instanceof MissingConfig) {\n details = html`\n <p><b>Missing Required Config Options:</b></p>\n <p>${error.missingConfigKeyNames.join(\", \")}</p>\n `;\n }\n return html`<div class=\"beam-error\" style=\"text-align: left\">\n <p>${strings.errorTitle} ${retry ? html` <button type=\"reset\" @click=\"${retry}\">${strings.retry}</button>` : \"\"}</p>\n <br />\n <details>\n <div style=\"white-space: pre-wrap; font-family: monospace; line-height: 1;\">\n ${details}\n <p><b>Message:</b> ${error.message || html`<i>None</i>`}</p>\n <p><b>Stack:</b> ${error.stack}</p>\n </div>\n </details>\n <br />\n <p>Help: <a href=\"https://www.beamimpact.com\">www.beamimpact.com</a></p>\n </div>`;\n};\n","import { html } from \"lit\";\n\nconst strings = {\n loading: \"\", // Default is no loading content\n};\n\nexport const _loading = () => {\n return html`<p class=\"beam-loading\">${strings.loading}</p>`;\n};\n","import { CSSResult, unsafeCSS } from \"lit\";\n\n/**\n * Create an object that can be passed to cssVariableMap\n * to define CSS variables in a style tag. The default properties\n * are the ones exposed for customization in the remote config interface.\n * @example\n * const variables = {\n * ...customizableTextJs(\"widget-header\",\n * \"widget-border-color\": \"red\"\n * };\n *\n * html`<style>:host { ${_cssVariableMap(variables)} }</style>`;\n * @returns {{[p: string]: string}}\n */\nexport const defineCustomText = (\n namespace = \"\",\n {\n fontFamily = \"inherit\",\n fontStyle = \"inherit\",\n fontSize = \"inherit\",\n fontWeight = \"inherit\",\n textTransform = \"none\",\n textDecoration = \"none\",\n marginTop = \"0\",\n lineHeight = \"inherit\",\n color = \"inherit\",\n letterSpacing = \"normal\",\n } = {},\n): Record<string, string> => {\n const prefix = namespace.startsWith(\"--beam-\") ? namespace : `--beam-${namespace}`;\n return {\n [`${prefix}-fontFamily`]: fontFamily,\n [`${prefix}-fontStyle`]: fontStyle,\n [`${prefix}-fontSize`]: fontSize,\n [`${prefix}-fontWeight`]: fontWeight,\n [`${prefix}-textTransform`]: textTransform,\n [`${prefix}-marginTop`]: marginTop,\n [`${prefix}-lineHeight`]: lineHeight,\n [`${prefix}-color`]: color,\n [`${prefix}-letterSpacing`]: letterSpacing,\n [`${prefix}-textDecoration`]: textDecoration,\n };\n};\n\n/**\n * Returns a string that defines css properties based on variables,\n * which can be used in a css`` template. The default properties are the\n * ones exposed for customization in the remote config interface.\n * @example\n * css`.widget-header { ${customizableTextCss(\"widget-header\")} border: none; }`\n * @returns {CSSResult}\n */\nexport const useCustomText = (\n namespace = \"\",\n {\n fontFamily = \"inherit\",\n fontStyle = \"inherit\",\n fontSize = \"inherit\",\n fontWeight = \"inherit\",\n textTransform = \"none\",\n textDecoration = \"none\",\n marginTop = \"0\",\n lineHeight = \"inherit\",\n color = \"inherit\",\n letterSpacing = \"normal\",\n } = {},\n): CSSResult => {\n const prefix = namespace.startsWith(\"--beam-\") ? namespace : `--beam-${namespace}`;\n return unsafeCSS(`\\\n font-family: var(${prefix}-fontFamily, ${fontFamily});\n font-style: var(${prefix}-fontStyle, ${fontStyle});\n font-size: var(${prefix}-fontSize, ${fontSize});\n font-weight: var(${prefix}-fontWeight, ${fontWeight});\n text-transform: var(${prefix}-textTransform, ${textTransform});\n margin-top: var(${prefix}-marginTop, ${marginTop});\n line-height: var(${prefix}-lineHeight, ${lineHeight});\n text-decoration: var(${prefix}-textDecoration, ${textDecoration});\n color: var(${prefix}-color, ${color});\n letter-spacing: var(${prefix}-letterSpacing, ${letterSpacing});\n `);\n};\n\n/**\n * Same as useCustomText except returns an object that can be passed to styleMap\n */\nexport const useCustomTextMap = (\n namespace = \"\",\n {\n fontSize = \"inherit\",\n fontStyle = \"inherit\",\n fontWeight = \"inherit\",\n textTransform = \"none\",\n textDecoration = \"none\",\n marginTop = \"0\",\n lineHeight = \"inherit\",\n letterSpacing = \"normal\",\n } = {},\n): Record<string, string> => {\n const prefix = namespace.startsWith(\"--beam-\") ? namespace : `--beam-${namespace}`;\n return {\n fontSize: `var(${prefix}-fontSize, ${fontSize})`,\n fontStyle: `var(${prefix}-fontStyle, ${fontStyle})`,\n fontWeight: `var(${prefix}-fontWeight, ${fontWeight})`,\n textTransform: `var(${prefix}-textTransform, ${textTransform})`,\n textDecoration: `var(${prefix}-textDecoration, ${textDecoration})`,\n marginTop: `var(${prefix}-marginTop, ${marginTop})`,\n lineHeight: `var(${prefix}-lineHeight, ${lineHeight})`,\n letterSpacing: `var(${prefix}-letterSpacing, ${letterSpacing})`,\n };\n};\n","import { LANGUAGES } from \"../api-sdk/types\";\nimport { logger } from \"../utils/logger\";\nimport { BeamError } from \"../utils/beam-errors\";\n\n/**\n * User-provided strings may include embedded translations in JSON form\n * This function extracts the string for the provided language\n * If it fails to parse, or the string is not json-like, it returns the whole string\n */\nconst localizeUserString = (lang: LANGUAGES, str: string): string => {\n const isJson = str.startsWith(\"{\") && !str.startsWith(\"{{\");\n if (isJson) {\n try {\n const json = JSON.parse(str);\n return json[lang] ?? json[\"en\"] ?? str;\n } catch (err) {\n logger.error(new BeamError(\"Failed to extract JSON translation from string\"), str);\n return str;\n }\n }\n return str;\n};\n\nexport { localizeUserString };\n","export const isAllHtmlElements = (a: Array<unknown>): a is Array<HTMLElement> => {\n return a.every((el) => el instanceof HTMLElement);\n};\n","import { paths } from \"../api-sdk/openapi-spec\";\nimport { BEAM_COOKIE_NAMES } from \"../api-sdk/constants\";\nexport type TCartApi =\n paths[\"/chain/findEligibleNonprofitsForCart\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"][\"cart\"];\n\n// Same as type from API but with non-optional fields, so we can use where Shopify guarantees values\nexport type TCart = TCartApi & {\n content: {\n items: Record<string, any>[];\n discounts?: Record<string, any>[] | undefined | null;\n };\n};\n\nexport type TCartItems = TCart[\"content\"][\"items\"];\n\nexport type TCartDiscounts = TCart[\"content\"][\"discounts\"];\n\nexport type TBeamCartLocalStorage = {\n cartId: string;\n beamCartId?: string;\n subtotal: number;\n itemCount: number;\n currencyCode: string;\n} & TCart;\n\nexport const BEAM_CART_COOKIE_NAME = BEAM_COOKIE_NAMES.CART;\n\nexport type Discount = {\n code: string;\n applicable: boolean;\n};\n","import { postLogs } from \"../../api-sdk/v3/routes\";\nimport { logger } from \"../../utils/logger\";\nimport { DEFAULT_LOG_URL } from \"../../api-sdk/constants\";\nimport { paths } from \"../../api-sdk/openapi-spec\";\n\ntype PostLogsReq = paths[\"/logs\"][\"post\"][\"requestBody\"][\"content\"][\"application/json\"];\n\ninterface SendLogConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport async function sendLog(config: SendLogConfig, payload: PostLogsReq): Promise<void> {\n const { apiKey, baseUrl } = config;\n try {\n await postLogs({\n baseUrl: baseUrl || DEFAULT_LOG_URL,\n headers: {\n authorization: `Api-Key ${apiKey}`,\n },\n requestBody: {\n ...payload,\n },\n });\n } catch (err) {\n logger.error(\"Failed to send log\", err);\n }\n}\n"],"names":["_cssVariableMap","variables","k","v","AsyncController","host","asyncFn","args","err","fetchJson","url","options","fetchOptions","pkgVersion","response","error","BeamError","logger","body","text","NetworkError","makeOpenApiMethod","pathName","method","okHttpStatus","headers","baseUrl","DEFAULT_BASE_URL","apiRoot","pathParams","queryParams","requestBody","keepalive","pathWithParams","newPath","cleanQueryParams","search","getImpact","getCumulativeImpact","postSelectNonprofit","postCart","postChainEligibleNonprofitsForCart","memoizeLast","postLogs","postExperimentSession","updateSubscription","postFindOrCreateSubscription","postProductDetailsPage","strings","_errorMessage","retry","details","html","MissingConfig","_loading","defineCustomText","namespace","fontFamily","fontStyle","fontSize","fontWeight","textTransform","textDecoration","marginTop","lineHeight","color","letterSpacing","prefix","useCustomText","unsafeCSS","localizeUserString","lang","str","json","isAllHtmlElements","a","el","BEAM_CART_COOKIE_NAME","BEAM_COOKIE_NAMES","sendLog","config","payload","apiKey","DEFAULT_LOG_URL"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as o,r as c,a as R,b as g}from"./lit-BEag9MFp.esm.js";import{D as v,A as P,h as B,_ as M,$ as N,E as F,v as x,g as y,l as L,n as w,a1 as W,L as T,a2 as J,Y as k,u as q,G as z,Q as G,w as Y}from"./utils-ly9wMwUO.esm.js";import{c as j,d as V,e as Q}from"./css-card-grid-tjA36yWj.esm.js";import{B as U,A as H,c as X}from"./index-
|
|
1
|
+
import{n as o,r as c,a as R,b as g}from"./lit-BEag9MFp.esm.js";import{D as v,A as P,h as B,_ as M,$ as N,E as F,v as x,g as y,l as L,n as w,a1 as W,L as T,a2 as J,Y as k,u as q,G as z,Q as G,w as Y}from"./utils-ly9wMwUO.esm.js";import{c as j,d as V,e as Q}from"./css-card-grid-tjA36yWj.esm.js";import{B as U,A as H,c as X}from"./index-BlaOItQr.esm.js";import{p as Z,u as tt}from"./index-C6QfHWnX.esm.js";import"../components/impact-overview.js";var et=Object.defineProperty,e=(h,s,n,m)=>{for(var d=void 0,p=h.length-1,u;p>=0;p--)(u=h[p])&&(d=u(s,n,d)||d);return d&&et(s,n,d),d};const A=["baseUrl","apiKey","orderId","cartTotal","currencyCode","lang"],ot=["storeId","postalCode","countryCode","cart","discountCodes","promoCodes","htmlPromoCodes","email","partnerUserId","remoteSessionId"];class t extends R{constructor(){super(...arguments),this.baseUrl=v,this.currencyCode="USD",this.lang="en",this.debug=!1,this.activeWidget=null,this.nonprofitId=null,this.selectionId=null,this.cartId=null,this.beamCartId=null,this.userId=null,this.transactionId=null,this.excludeDonationsForRecurringTransactions=!1,this.creationMethod="",this.orderProcessedAt="",this.draftConfig=!1,this.localStorage=P(this),this.handlePostTransaction=async()=>{this.enforceConfig(),this.updateComponentState();const s=this.getManualPromoCodes(),n=B(s.map(a=>({value:a})),this.apiKey),m=M(),d={unvalidatedPromoCodes:N(s.map(a=>({value:a}))),validatedPromoCodes:m?.validatedPromoCodes??[]},p=n??d,u=p&&!F(p),I=this.remoteSessionId??x({apiKey:this.apiKey})??y("beam_statsig_session_id"),i=await Z({baseUrl:this.baseUrl,apiRoot:"/api",headers:{authorization:`Api-Key ${this.apiKey}`},requestBody:{selectionId:this.selectionId||void 0,cartId:this.cartId||void 0,beamCartId:this.beamCartId||void 0,storeId:this.storeId,orderId:this.orderId,cartTotal:this.cartTotal,email:this.email,partnerUserId:this.partnerUserId,currencyCode:this.currencyCode,...this.postalCode&&{postalCode:this.postalCode},...this.countryCode&&{countryCode:this.countryCode},cart:this.cart,...u&&{promos:p},discountCodes:this.discountCodes,orderProcessedAt:new Date().toISOString(),...I&&{remoteSessionId:I}}});let l=i;if(!i.transactionCreated&&!i.selectionId&&this.selectionId)try{const a=await tt({baseUrl:this.baseUrl,apiRoot:"/api",headers:{authorization:`Api-Key ${this.apiKey}`},pathParams:{transactionId:i.transactionId},requestBody:{selectionId:this.selectionId}});l=a,this.selectionId=a.selectionId??this.selectionId,this.localStorage.removeItem("transaction")}catch(a){L.warn(new w("Failed to attach selectionId to existing transaction via update endpoint",{cause:a}),{transactionId:i.transactionId,selectionId:this.selectionId})}this.transactionId=l.transactionId,this.userId=l.beamUserId,this.nonprofitId=l.nonprofitId,this.excludeDonationsForRecurringTransactions=!!i.reportSettings?.excludeRecurringDonations,this.creationMethod=l.creationMethod||"",this.orderProcessedAt=l.timestamp;const C=!!this.nonprofitId;return this.activeWidget=C?"impact-overview":"redeem-transaction",i.transactionCreated&&(["transaction","cart",W,T.NONPROFIT,T.NONPROFIT_SELECTED_AT].forEach(a=>{this.localStorage.removeItem(a)}),[{name:U,path:"/",domain:this.domain},{name:J,path:"/",domain:this.domain}].forEach(a=>k(a)),dispatchEvent(new q({transactionId:i.transactionId,orderId:this.orderId,cartTotal:this.cartTotal,currencyCode:this.currencyCode,selectionId:this.selectionId??null,cartId:this.cartId,beamCartId:this.beamCartId,storeId:this.storeId??null,postalCode:this.postalCode??null,countryCode:this.countryCode??null,remoteSessionId:this.remoteSessionId??null,transactionNonprofitId:i.nonprofitId,orderProcessedAt:i.timestamp}))),l},this.transactionDataController=new H(this,this.handlePostTransaction)}get parsedPromoCodes(){return z(this.htmlPromoCodes)}updateComponentState(){this.localStorage.getItem("transaction")?.toLocaleLowerCase()==="undefined"&&this.localStorage.removeItem("transaction"),this.selectionId=this.selectionId||this.localStorage.getItem("transaction")||null,this.cartId=this.cartId||this.localStorage.getItemJson("cart")?.cartId||null,this.beamCartId=this.beamCartId||this.localStorage.getItemJson("cart")?.beamCartId||y(U)||null,this.selectionId&&this.nonprofitId&&(this.activeWidget="impact-overview")}firstUpdated(s){this.enforceConfig(),this.updateComponentState()}async updated(s){[...A,...ot].some(n=>s.has(n))&&await this.transactionDataController.exec()}enforceConfig(){if(Q(A,this),!this.email&&!this.partnerUserId)throw new G([this.email?"":"email",this.partnerUserId?"":"partnerUserId"].filter(Boolean),"At least one of [email, partnerUserId] must be provided")}getManualPromoCodes(){return this.parsedPromoCodes?.length?this.parsedPromoCodes:this.promoCodes?.length?this.promoCodes:[]}render(){const s=Date.now()-new Date(this.orderProcessedAt).getTime()<2592e6;return this.transactionDataController.loading?"":this.transactionDataController.error?this.debug?X({error:this.transactionDataController.error}):"":this.excludeDonationsForRecurringTransactions&&this.creationMethod==="recurring"?g``:this.activeWidget==="redeem-transaction"&&s?g`
|
|
2
2
|
<beam-redeem-transaction
|
|
3
3
|
part="redeem-transaction"
|
|
4
4
|
baseUrl="${this.baseUrl}"
|
|
@@ -29,4 +29,4 @@ import{n as o,r as c,a as R,b as g}from"./lit-BEag9MFp.esm.js";import{D as v,A a
|
|
|
29
29
|
?debug="${this.debug}"
|
|
30
30
|
></beam-impact-overview>
|
|
31
31
|
`:""}}t.tagName="beam-post-purchase",t.styles=[j],e([o({type:String})],t.prototype,"baseUrl"),e([o({type:String})],t.prototype,"apiKey"),e([o({type:Number,reflect:!0})],t.prototype,"storeId"),e([o({type:String})],t.prototype,"postalCode"),e([o({type:String})],t.prototype,"countryCode"),e([o({type:String})],t.prototype,"orderId"),e([o({type:String})],t.prototype,"email"),e([o({type:String})],t.prototype,"partnerUserId"),e([o({type:Number})],t.prototype,"cartTotal"),e([o({type:String})],t.prototype,"currencyCode"),e([o({type:String})],t.prototype,"lang"),e([o({type:Object})],t.prototype,"cart"),e([o({type:Array})],t.prototype,"discountCodes"),e([o({type:Array})],t.prototype,"promoCodes"),e([o({type:String})],t.prototype,"htmlPromoCodes"),e([o({type:String})],t.prototype,"domain"),e([o({type:String})],t.prototype,"remoteSessionId"),e([o({type:Boolean})],t.prototype,"debug"),e([c()],t.prototype,"activeWidget"),e([c()],t.prototype,"nonprofitId"),e([c()],t.prototype,"selectionId"),e([c()],t.prototype,"cartId"),e([c()],t.prototype,"beamCartId"),e([c()],t.prototype,"userId"),e([c()],t.prototype,"transactionId"),e([c()],t.prototype,"excludeDonationsForRecurringTransactions"),e([c()],t.prototype,"creationMethod"),e([c()],t.prototype,"orderProcessedAt"),e([o({type:Boolean})],t.prototype,"draftConfig"),V(t);async function rt({parentSelector:h=".step__sections",apiKey:s,baseUrl:n=v,storeId:m,postalCode:d,discountCodes:p,countryCode:u,orderId:I,email:i,cartTotal:l,cart:C,promoCodes:a,htmlPromoCodes:E,currencyCode:$="USD",domain:O,lang:D="en",debug:_=!1}){const f=document.querySelector(h)||await Y(h);if(!f)throw new w(`Timed out waiting for selector '${h}'. Could not render Beam post-purchase widget.`);const S=await y("cart");if(S){const b=P({apiKey:s}),K=b.getItemJson("cart")||{};b.setItemJson("cart",{...K,cartId:S})}const r=document.createElement("beam-post-purchase");r.apiKey=s,r.baseUrl=n,r.storeId=m,r.postalCode=d,r.countryCode=u,r.orderId=String(I),r.email=i,r.cartTotal=l,r.cart=C,r.promoCodes=a,r.htmlPromoCodes=E,r.discountCodes=p,r.currencyCode=$,r.domain=O,r.lang=D,r.debug=_,f.appendChild(r)}export{t as B,rt as s};
|
|
32
|
-
//# sourceMappingURL=index-
|
|
32
|
+
//# sourceMappingURL=index-BtG64tE0.esm.js.map
|