@behindthescenes/cart 0.0.24 → 0.0.25
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/browser/browser.js +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/manifest.json +2 -2
- package/package.json +1 -1
package/dist/browser/browser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var Q="https://api.bts.it.com/v2/website/cart",S="bts-cart",q="default",z=2;function D(){try{return globalThis.window??null}catch{return null}}function O(){try{return globalThis.localStorage??D()?.localStorage??null}catch{return null}}var w=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],b=["fbclid","gclid","gbraid","wbraid","ttclid","li_fat_id","msclkid","_fbp","_fbc"];function x(B){if(!B)return{utm:{},clickIds:{}};try{let F=JSON.parse(B);if(!F||typeof F!=="object"||Array.isArray(F))return{utm:{},clickIds:{}};let N=F,G=N.utm&&typeof N.utm==="object"&&!Array.isArray(N.utm)?Object.fromEntries(Object.entries(N.utm).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{},Z=N.clickIds&&typeof N.clickIds==="object"&&!Array.isArray(N.clickIds)?Object.fromEntries(Object.entries(N.clickIds).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{};return{utm:G,clickIds:Z}}catch{return{utm:{},clickIds:{}}}}function C(B,F){let N=new URL(B);N.searchParams.set("bts_site",F);let G=O(),Z=G?.getItem("bts_analytics_jt")?.trim();if(Z)N.searchParams.set("bts_jt",Z);let{utm:X,clickIds:J}=x(G?.getItem("bts_analytics_attr")??null);for(let Y of w){let V=X[Y];if(V)N.searchParams.set(Y,V)}for(let Y of b){let V=J[Y];if(V)N.searchParams.set(Y,V)}return N.toString()}class $ extends Error{code;status;available;sold_out;quantity_exceeded;details;constructor(B,F,N,G,Z,X,J){super(F);this.name="BTSCartError",this.code=B,this.status=N,this.details=G,this.available=Z,this.sold_out=X,this.quantity_exceeded=J}}function f(){return O()??void 0}function p(B){return(B??Q).replace(/\/$/,"")}function I(B){if(!Number.isFinite(B??1))return 1;return Math.max(1,Math.floor(B??1))}function R(B){return{items:B.map((F)=>({...F}))}}function U(B){let F=B?.trim();return F&&F.length>0?F:void 0}function g(B){return B.accessTierId??B.productId??B.lineItemId}function h(B){if(B.discountEligibleTierOrProductIds?.length)return[...new Set(B.discountEligibleTierOrProductIds.filter(Boolean))];return[...new Set([B.accessTierId,B.productId,B.lineItemId].filter((F)=>Boolean(F)))]}function W(B){let F=new Set;for(let N of B)for(let G of[N.lineItemId,N.accessTierId,N.productId])if(G)F.add(G);return B.map((N)=>{if(!N.discount)return N;let G=h(N);if(G.length===0||!G.some((Z)=>F.has(Z))){let Z={...N};return delete Z.discount,delete Z.discountEligibleTierOrProductIds,Z}return N})}function y(B,F){let N=new Headers(B);if(!F)return N;return new Headers(F).forEach((G,Z)=>N.set(Z,G)),N}function _(B){let F=B.checkoutLinkId.trim();try{let N=F.includes("://")?F:F.startsWith("/")?`https://bts-cart.invalid${F}`:F,G=new URL(N),Z=G.pathname.split("/").filter(Boolean),X=Z.indexOf("c"),J=X>=0?Z[X+1]:Z.at(-1);if(J)return{checkoutLinkId:J,discountCode:B.discountCode??G.searchParams.get("discountCode")??void 0}}catch{}return{checkoutLinkId:F,discountCode:B.discountCode}}function k(B){let F=B?.details;if(!Array.isArray(F))return;let N=F.flatMap((G)=>{if(!G||typeof G!=="object")return[];let Z=typeof G.lineItemId==="string"?G.lineItemId:"",X=typeof G.reason==="string"?G.reason:"";if(!Z||!X)return[];let J=typeof G.discountCode==="string"?G.discountCode:void 0,Y=typeof G.requestedQuantity==="number"?G.requestedQuantity:void 0,V=typeof G.adjustedQuantity==="number"?G.adjustedQuantity:void 0;if(!J&&!(Y!==void 0||V!==void 0||X==="line_item_sold_out"||X==="quantity_exceeded"||X==="product_unavailable"))return[];return[{lineItemId:Z,...typeof G.productId==="string"?{productId:G.productId}:{},...typeof G.accessTierId==="string"?{accessTierId:G.accessTierId}:{},...J?{discountCode:J}:{},...typeof G.discountId==="string"?{discountId:G.discountId}:{},reason:X,...Y!==void 0?{requestedQuantity:Y}:{},...V!==void 0?{adjustedQuantity:V}:{}}]});return N.length>0?N:void 0}var u=new Set(["discounts_invalid","quantity_invalid","cart_adjusted"]);function A(B){return u.has(B)}function c(B){return[...new Set([B.lineItemId,B.accessTierId,B.productId].filter((F)=>Boolean(F)))]}function P(B,F){let N=c(B);return[F.lineItemId,F.accessTierId,F.productId].filter((Z)=>Boolean(Z)).some((Z)=>N.includes(Z))}class H{siteKey;endpoint;debug;persist;storageKey;storage;checkoutLinks;defaultCheckoutLinkKey;requestHeaders;items=[];listeners=new Set;constructor(B){this.siteKey=B.siteKey,this.endpoint=p(B.endpoint),this.debug=B.debug??!1,this.persist=B.persist??!0,this.storageKey=B.storageKey??S,this.storage=B.storage??f(),this.checkoutLinks=B.checkoutLinks??{},this.defaultCheckoutLinkKey=B.defaultCheckoutLinkKey??Object.keys(this.checkoutLinks)[0]??q,this.requestHeaders=B.requestHeaders,this.rehydrate()}static init(B){return new H(B)}getItems(){return R(this.items).items}getState(){return R(this.items)}getItemCount(){return this.items.reduce((B,F)=>B+F.quantity,0)}getSubtotal(){return this.items.reduce((B,F)=>B+(F.fullPrice??F.unitPrice)*F.quantity,0)}getTotal(){return this.items.reduce((B,F)=>B+F.unitPrice*F.quantity,0)}subscribe(B){return this.listeners.add(B),B(this.getState()),()=>{this.listeners.delete(B)}}destroy(){this.listeners.clear()}rehydrate(){if(!this.persist||!this.storage)return;try{let B=this.storage.getItem(this.storageKey);if(!B)return;let F=JSON.parse(B);if(Array.isArray(F)||F.version!==z){this.storage.removeItem(this.storageKey);return}let N=F.items;if(!Array.isArray(N))return;this.items=W(N.map((G)=>this.normalizeItem(G)).filter((G)=>Boolean(G))),this.emit()}catch(B){this.log("Failed to hydrate cart",B)}}addItem(B){let F=this.normalizeItem(B);if(!F)return;let N=this.items.find((G)=>G.id===F.id);if(N){this.setQuantity(N.id,N.quantity+F.quantity);return}this.items=[...this.items,F],this.commit()}removeItem(B){this.items=this.items.filter((F)=>F.id!==B),this.commit()}setQuantity(B,F){let N=Math.floor(F);this.items=N<=0?this.items.filter((G)=>G.id!==B):this.items.map((G)=>G.id===B?{...G,quantity:N}:G),this.commit()}increment(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity+Math.max(1,Math.floor(F)))}decrement(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity-Math.max(1,Math.floor(F)))}clear(){if(this.items=[],this.persist&&this.storage)try{this.storage.removeItem(this.storageKey)}catch(B){this.log("Failed to clear cart storage",B)}this.emit()}removeDiscountForLineItem(B){this.items=this.items.map((F)=>{if(!P(F,{lineItemId:B,reason:"discount"}))return F;if(!F.discount)return F;let N={...F,unitPrice:F.fullPrice??F.unitPrice};return delete N.discount,delete N.discountEligibleTierOrProductIds,N}),this.commit()}async checkIfItemsAvailable(B){let F=[];for(let N of B){let G=await this.checkIfItemAvailable(this.defaultCheckoutLinkKey,N.lineItemId,N.discountId);if(G instanceof $)throw new $(G.code,G.message);F.push(G)}return F}async checkIfItemAvailable(B=this.defaultCheckoutLinkKey,F,N){let G=this.checkoutLinks[B];if(!G)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let Z=_(G),X={siteKey:this.siteKey,checkoutLinkId:Z.checkoutLinkId,mode:G.mode,lineItemId:F,...N?{discountId:N}:{}},J=await this.post("/check-availability",X);if(typeof J.ok!=="boolean")throw new $("request_failed","Availability check response was invalid.");return J}async validateCheckout(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=_(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/validate-discounts",Z);if(typeof X.ok!=="boolean")throw new $("request_failed","Cart response was invalid.");return X}catch(X){if(X instanceof $){if(A(X.code))throw this.reconcileCartAdjustments(X.details),new $(X.code,X.message,X.status,X.details);throw new $(X.code,X.message,X.status)}throw new $("request_failed","Failed to validate checkout.",void 0,void 0)}}async resolveCheckoutUrl(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=_(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/checkout-url",Z);if(X.ok!==!0||typeof X.checkoutUrl!=="string"||X.checkoutUrl.length===0)throw new $("request_failed","Cart response was invalid.");return C(X.checkoutUrl,this.siteKey)}catch(X){if(X instanceof $){if(A(X.code))throw this.reconcileCartAdjustments(X.details),new $(X.code,X.message,X.status,X.details);throw new $(X.code,X.message,X.status)}throw new $("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}async checkout(B=this.defaultCheckoutLinkKey){try{let F=await this.resolveCheckoutUrl(B),N=D();if(N)N.location.assign(F);return F}catch(F){if(F instanceof $){if(A(F.code))throw this.reconcileCartAdjustments(F.details),new $(F.code,F.message,F.status,F.details);throw new $(F.code,F.message,F.status)}throw new $("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}itemsForCheckout(B,F){if(F.mode==="static")return[];let N=this.items.filter((G)=>G.checkoutLinkKey===B).map((G)=>({lineItemId:g(G),quantity:G.quantity,...G.discount?{discount:G.discount}:{}}));if(N.length===0)throw new $("cart_empty","Your cart is empty.");return N}normalizeItem(B){let F=U(B.accessTierId),N=U(B.productId),G=U(B.lineItemId)??F??N;if(!B.id||!G||typeof B.unitPrice!=="number")return null;let Z=typeof B.name==="string"&&B.name.trim().length>0?B.name.trim():"Item";return{...B,id:B.id,lineItemId:G,...F?{accessTierId:F}:{},...N?{productId:N}:{},checkoutLinkKey:B.checkoutLinkKey??this.defaultCheckoutLinkKey,name:Z,unitPrice:B.unitPrice,quantity:I(B.quantity)}}reconcileCartAdjustments(B){if(!B?.length)return;let F=[...this.items],N=!1;for(let G of B){if(G.discountCode){F=F.map((X)=>{if(!P(X,G))return X;let J={...X,unitPrice:X.fullPrice??X.unitPrice};return delete J.discount,delete J.discountEligibleTierOrProductIds,N=!0,J});continue}if(G.reason==="line_item_sold_out"||G.reason==="product_unavailable"||G.adjustedQuantity===0){let X=F.length;if(F=F.filter((J)=>!P(J,G)),F.length!==X)N=!0;continue}if(G.reason==="quantity_exceeded"&&typeof G.adjustedQuantity==="number"&&G.adjustedQuantity>0)F=F.map((X)=>{if(!P(X,G))return X;return N=!0,{...X,quantity:G.adjustedQuantity}})}if(!N)return;this.items=F,this.commit()}async post(B,F){let N=`${this.endpoint}${B}`,G=JSON.stringify(F),Z={"Content-Type":"application/json"},X={body:F,bodyText:G,endpoint:this.endpoint,headers:Z,path:B,siteKey:this.siteKey,url:N},J=typeof this.requestHeaders==="function"?await this.requestHeaders(X):this.requestHeaders,Y=y(Z,J),V=await fetch(N,{method:"POST",headers:Y,body:G}),E=await V.json().catch(()=>null);if(!V.ok){let K=typeof E?.code==="string"&&E.code.length>0?E.code:"request_failed",L=typeof E?.message==="string"&&E.message.length>0?E.message:"Cart request failed";throw new $(K,L,V.status,k(E))}if(!E||typeof E!=="object")throw new $("request_failed","Cart response was invalid.",V.status);return E}commit(){if(this.items=W(this.items),this.persist&&this.storage)try{let B={version:z,items:this.items};this.storage.setItem(this.storageKey,JSON.stringify(B))}catch(B){this.log("Failed to persist cart",B)}this.emit()}emit(){let B=this.getState();for(let F of this.listeners)F(B)}log(...B){if(this.debug)console.log("[@behindthescenes/cart]",...B)}}function T(B){return H.init(B)}function j(B){return typeof B==="object"&&B!==null&&!Array.isArray(B)}function v(B){let F=D();if(!F)return;let[N,G,Z]=B;if(typeof N!=="string")return;if(N==="config"){if(!j(G))return;F.btsCart?.destroy?.(),F.btsCart=T(G);return}let X=F.btsCart;if(!X)return;if(N==="add"&&j(G)){X.addItem(G);return}if(N==="remove"&&typeof G==="string"){X.removeItem(G);return}if(N==="quantity"&&typeof G==="string"&&typeof Z==="number"){X.setQuantity(G,Z);return}if(N==="clear"){X.clear();return}if(N==="checkout")X.checkout(typeof G==="string"?G:void 0)}var M=D();if(M){let B=Array.isArray(M.btsCartDataLayer)?[...M.btsCartDataLayer]:[];M.btsCartDataLayer=Array.isArray(M.btsCartDataLayer)?M.btsCartDataLayer:[],M.BTSCart={BTSCart:H,createBTSCart:T},M.createBTSCart=T;for(let F of B)v(Array.from(F));M.btsCartCommand=(...F)=>{M.btsCartDataLayer?.push(F),v(F)}}export{T as createBTSCart,H as BTSCart};
|
|
1
|
+
var S="https://api.bts.it.com/v2/website/cart",Q="bts-cart",q="default",z=2;function D(){try{return globalThis.window??null}catch{return null}}function O(){try{return globalThis.localStorage??D()?.localStorage??null}catch{return null}}var w=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],b=["fbclid","gclid","gbraid","wbraid","ttclid","li_fat_id","msclkid","_fbp","_fbc"];function x(B){if(!B)return{utm:{},clickIds:{}};try{let F=JSON.parse(B);if(!F||typeof F!=="object"||Array.isArray(F))return{utm:{},clickIds:{}};let N=F,G=N.utm&&typeof N.utm==="object"&&!Array.isArray(N.utm)?Object.fromEntries(Object.entries(N.utm).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{},Z=N.clickIds&&typeof N.clickIds==="object"&&!Array.isArray(N.clickIds)?Object.fromEntries(Object.entries(N.clickIds).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{};return{utm:G,clickIds:Z}}catch{return{utm:{},clickIds:{}}}}function C(B,F){let N=new URL(B);N.searchParams.set("bts_site",F);let G=O(),Z=G?.getItem("bts_analytics_jt")?.trim();if(Z)N.searchParams.set("bts_jt",Z);let{utm:X,clickIds:$}=x(G?.getItem("bts_analytics_attr")??null);for(let E of w){let Y=X[E];if(Y)N.searchParams.set(E,Y)}for(let E of b){let Y=$[E];if(Y)N.searchParams.set(E,Y)}return N.toString()}class J extends Error{code;status;available;sold_out;quantity_exceeded;details;constructor(B,F,N,G,Z,X,$){super(F);this.name="BTSCartError",this.code=B,this.status=N,this.details=G,this.available=Z,this.sold_out=X,this.quantity_exceeded=$}}function f(){return O()??void 0}function p(B){return(B??S).replace(/\/$/,"")}function I(B){if(!Number.isFinite(B??1))return 1;return Math.max(1,Math.floor(B??1))}function R(B){return{items:B.map((F)=>({...F}))}}function U(B){let F=B?.trim();return F&&F.length>0?F:void 0}function g(B){return B.accessTierId??B.productId??B.lineItemId}function h(B){if(B.discountEligibleTierOrProductIds?.length)return[...new Set(B.discountEligibleTierOrProductIds.filter(Boolean))];return[...new Set([B.accessTierId,B.productId,B.lineItemId].filter((F)=>Boolean(F)))]}function W(B){let F=new Set;for(let N of B)for(let G of[N.lineItemId,N.accessTierId,N.productId])if(G)F.add(G);return B.map((N)=>{if(!N.discount)return N;let G=h(N);if(G.length===0||!G.some((Z)=>F.has(Z))){let Z={...N};return delete Z.discount,delete Z.discountEligibleTierOrProductIds,Z}return N})}function y(B,F){let N=new Headers(B);if(!F)return N;return new Headers(F).forEach((G,Z)=>N.set(Z,G)),N}function _(B){let F=B.checkoutLinkId.trim();try{let N=F.includes("://")?F:F.startsWith("/")?`https://bts-cart.invalid${F}`:F,G=new URL(N),Z=G.pathname.split("/").filter(Boolean),X=Z.indexOf("c"),$=X>=0?Z[X+1]:Z.at(-1);if($)return{checkoutLinkId:$,discountCode:B.discountCode??G.searchParams.get("discountCode")??void 0}}catch{}return{checkoutLinkId:F,discountCode:B.discountCode}}function k(B){let F=B?.details;if(!Array.isArray(F))return;let N=F.flatMap((G)=>{if(!G||typeof G!=="object")return[];let Z=typeof G.lineItemId==="string"?G.lineItemId:"",X=typeof G.reason==="string"?G.reason:"";if(!Z||!X)return[];let $=typeof G.discountCode==="string"?G.discountCode:void 0,E=typeof G.requestedQuantity==="number"?G.requestedQuantity:void 0,Y=typeof G.adjustedQuantity==="number"?G.adjustedQuantity:void 0;if(!$&&!(E!==void 0||Y!==void 0||X==="line_item_sold_out"||X==="quantity_exceeded"||X==="product_unavailable"))return[];return[{lineItemId:Z,...typeof G.productId==="string"?{productId:G.productId}:{},...typeof G.accessTierId==="string"?{accessTierId:G.accessTierId}:{},...$?{discountCode:$}:{},...typeof G.discountId==="string"?{discountId:G.discountId}:{},reason:X,...E!==void 0?{requestedQuantity:E}:{},...Y!==void 0?{adjustedQuantity:Y}:{}}]});return N.length>0?N:void 0}var u=new Set(["discounts_invalid","quantity_invalid","cart_adjusted"]);function A(B){return u.has(B)}function c(B){return[...new Set([B.lineItemId,B.accessTierId,B.productId].filter((F)=>Boolean(F)))]}function P(B,F){let N=c(B);return[F.lineItemId,F.accessTierId,F.productId].filter((Z)=>Boolean(Z)).some((Z)=>N.includes(Z))}class H{siteKey;endpoint;debug;persist;storageKey;storage;checkoutLinks;defaultCheckoutLinkKey;requestHeaders;items=[];listeners=new Set;constructor(B){this.siteKey=B.siteKey,this.endpoint=p(B.endpoint),this.debug=B.debug??!1,this.persist=B.persist??!0,this.storageKey=B.storageKey??Q,this.storage=B.storage??f(),this.checkoutLinks=B.checkoutLinks??{},this.defaultCheckoutLinkKey=B.defaultCheckoutLinkKey??Object.keys(this.checkoutLinks)[0]??q,this.requestHeaders=B.requestHeaders,this.rehydrate()}static init(B){return new H(B)}getItems(){return R(this.items).items}getState(){return R(this.items)}getItemCount(){return this.items.reduce((B,F)=>B+F.quantity,0)}getSubtotal(){return this.items.reduce((B,F)=>B+(F.fullPrice??F.unitPrice)*F.quantity,0)}getTotal(){return this.items.reduce((B,F)=>B+F.unitPrice*F.quantity,0)}subscribe(B){return this.listeners.add(B),B(this.getState()),()=>{this.listeners.delete(B)}}destroy(){this.listeners.clear()}rehydrate(){if(!this.persist||!this.storage)return;try{let B=this.storage.getItem(this.storageKey);if(!B)return;let F=JSON.parse(B);if(Array.isArray(F)||F.version!==z){this.storage.removeItem(this.storageKey);return}let N=F.items;if(!Array.isArray(N))return;this.items=W(N.map((G)=>this.normalizeItem(G)).filter((G)=>Boolean(G))),this.emit()}catch(B){this.log("Failed to hydrate cart",B)}}addItem(B){let F=this.normalizeItem(B);if(!F)return;let N=this.items.find((G)=>G.id===F.id);if(N){this.setQuantity(N.id,N.quantity+F.quantity);return}this.items=[...this.items,F],this.commit()}removeItem(B){this.items=this.items.filter((F)=>F.id!==B),this.commit()}setQuantity(B,F){let N=Math.floor(F);this.items=N<=0?this.items.filter((G)=>G.id!==B):this.items.map((G)=>G.id===B?{...G,quantity:N}:G),this.commit()}increment(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity+Math.max(1,Math.floor(F)))}decrement(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity-Math.max(1,Math.floor(F)))}clear(){if(this.items=[],this.persist&&this.storage)try{this.storage.removeItem(this.storageKey)}catch(B){this.log("Failed to clear cart storage",B)}this.emit()}removeDiscountForLineItem(B){this.items=this.items.map((F)=>{if(!P(F,{lineItemId:B,reason:"discount"}))return F;if(!F.discount)return F;let N={...F,unitPrice:F.fullPrice??F.unitPrice};return delete N.discount,delete N.discountEligibleTierOrProductIds,N}),this.commit()}async checkIfItemsAvailable(B){let F=[];for(let N of B){let G=await this.checkIfItemAvailable(this.defaultCheckoutLinkKey,N.lineItemId,N.discountId);if(G instanceof J)throw new J(G.code,G.message);F.push(G)}return F}async checkIfItemAvailable(B=this.defaultCheckoutLinkKey,F,N){let G=this.checkoutLinks[B];if(!G)throw new J("checkout_link_not_found",`Unknown checkout link key: ${B}`);let Z=_(G),X={siteKey:this.siteKey,checkoutLinkId:Z.checkoutLinkId,mode:G.mode,lineItemId:F,...N?{discountId:N}:{}};try{let $=await this.post("/check-availability",X);if(typeof $.ok!=="boolean")throw new J("request_failed","Availability check response was invalid.");return $}catch($){if($ instanceof J){if($.details?.length)this.reconcileCartAdjustments($.details);if($.code==="line_item_sold_out"||$.code==="product_unavailable"||$.code==="quantity_exceeded")return{ok:!1,available:$.available??!1,sold_out:$.sold_out??$.code==="line_item_sold_out",quantity_exceeded:$.quantity_exceeded??($.code==="line_item_sold_out"||$.code==="quantity_exceeded")}}throw $}}async validateCheckout(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new J("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=_(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/validate-discounts",Z);if(typeof X.ok!=="boolean")throw new J("request_failed","Cart response was invalid.");return X}catch(X){if(X instanceof J){if(A(X.code))throw this.reconcileCartAdjustments(X.details),new J(X.code,X.message,X.status,X.details);throw new J(X.code,X.message,X.status)}throw new J("request_failed","Failed to validate checkout.",void 0,void 0)}}async resolveCheckoutUrl(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new J("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=_(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/checkout-url",Z);if(X.ok!==!0||typeof X.checkoutUrl!=="string"||X.checkoutUrl.length===0)throw new J("request_failed","Cart response was invalid.");return C(X.checkoutUrl,this.siteKey)}catch(X){if(X instanceof J){if(A(X.code))throw this.reconcileCartAdjustments(X.details),new J(X.code,X.message,X.status,X.details);throw new J(X.code,X.message,X.status)}throw new J("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}async checkout(B=this.defaultCheckoutLinkKey){try{let F=await this.resolveCheckoutUrl(B),N=D();if(N)N.location.assign(F);return F}catch(F){if(F instanceof J){if(A(F.code))throw this.reconcileCartAdjustments(F.details),new J(F.code,F.message,F.status,F.details);throw new J(F.code,F.message,F.status)}throw new J("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}itemsForCheckout(B,F){if(F.mode==="static")return[];let N=this.items.filter((G)=>G.checkoutLinkKey===B).map((G)=>({lineItemId:g(G),quantity:G.quantity,...G.discount?{discount:G.discount}:{}}));if(N.length===0)throw new J("cart_empty","Your cart is empty.");return N}normalizeItem(B){let F=U(B.accessTierId),N=U(B.productId),G=U(B.lineItemId)??F??N;if(!B.id||!G||typeof B.unitPrice!=="number")return null;let Z=typeof B.name==="string"&&B.name.trim().length>0?B.name.trim():"Item";return{...B,id:B.id,lineItemId:G,...F?{accessTierId:F}:{},...N?{productId:N}:{},checkoutLinkKey:B.checkoutLinkKey??this.defaultCheckoutLinkKey,name:Z,unitPrice:B.unitPrice,quantity:I(B.quantity)}}reconcileCartAdjustments(B){if(!B?.length)return;let F=[...this.items],N=!1;for(let G of B){if(G.discountCode){F=F.map((X)=>{if(!P(X,G))return X;let $={...X,unitPrice:X.fullPrice??X.unitPrice};return delete $.discount,delete $.discountEligibleTierOrProductIds,N=!0,$});continue}if(G.reason==="line_item_sold_out"||G.reason==="product_unavailable"||G.adjustedQuantity===0){let X=F.length;if(F=F.filter(($)=>!P($,G)),F.length!==X)N=!0;continue}if(G.reason==="quantity_exceeded"&&typeof G.adjustedQuantity==="number"&&G.adjustedQuantity>0){let X=G.adjustedQuantity;F=F.map(($)=>{if(!P($,G))return $;return N=!0,{...$,quantity:X}})}}if(!N)return;this.items=F,this.commit()}async post(B,F){let N=`${this.endpoint}${B}`,G=JSON.stringify(F),Z={"Content-Type":"application/json"},X={body:F,bodyText:G,endpoint:this.endpoint,headers:Z,path:B,siteKey:this.siteKey,url:N},$=typeof this.requestHeaders==="function"?await this.requestHeaders(X):this.requestHeaders,E=y(Z,$),Y=await fetch(N,{method:"POST",headers:E,body:G}),V=await Y.json().catch(()=>null);if(!Y.ok){let K=typeof V?.code==="string"&&V.code.length>0?V.code:"request_failed",L=typeof V?.message==="string"&&V.message.length>0?V.message:"Cart request failed";throw new J(K,L,Y.status,k(V),typeof V?.available==="boolean"?V.available:void 0,typeof V?.sold_out==="boolean"?V.sold_out:void 0,typeof V?.quantity_exceeded==="boolean"?V.quantity_exceeded:void 0)}if(!V||typeof V!=="object")throw new J("request_failed","Cart response was invalid.",Y.status);return V}commit(){if(this.items=W(this.items),this.persist&&this.storage)try{let B={version:z,items:this.items};this.storage.setItem(this.storageKey,JSON.stringify(B))}catch(B){this.log("Failed to persist cart",B)}this.emit()}emit(){let B=this.getState();for(let F of this.listeners)F(B)}log(...B){if(this.debug)console.log("[@behindthescenes/cart]",...B)}}function T(B){return H.init(B)}function v(B){return typeof B==="object"&&B!==null&&!Array.isArray(B)}function j(B){let F=D();if(!F)return;let[N,G,Z]=B;if(typeof N!=="string")return;if(N==="config"){if(!v(G))return;F.btsCart?.destroy?.(),F.btsCart=T(G);return}let X=F.btsCart;if(!X)return;if(N==="add"&&v(G)){X.addItem(G);return}if(N==="remove"&&typeof G==="string"){X.removeItem(G);return}if(N==="quantity"&&typeof G==="string"&&typeof Z==="number"){X.setQuantity(G,Z);return}if(N==="clear"){X.clear();return}if(N==="checkout")X.checkout(typeof G==="string"?G:void 0)}var M=D();if(M){let B=Array.isArray(M.btsCartDataLayer)?[...M.btsCartDataLayer]:[];M.btsCartDataLayer=Array.isArray(M.btsCartDataLayer)?M.btsCartDataLayer:[],M.BTSCart={BTSCart:H,createBTSCart:T},M.createBTSCart=T;for(let F of B)j(Array.from(F));M.btsCartCommand=(...F)=>{M.btsCartDataLayer?.push(F),j(F)}}export{T as createBTSCart,H as BTSCart};
|
package/dist/cjs/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var{defineProperty:O,getOwnPropertyNames:K,getOwnPropertyDescriptor:f}=Object,L=Object.prototype.hasOwnProperty;function x(B){return this[B]}var g=(B)=>{var F=(_??=new WeakMap).get(B),N;if(F)return F;if(F=O({},"__esModule",{value:!0}),B&&typeof B==="object"||typeof B==="function"){for(var G of K(B))if(!L.call(F,G))O(F,G,{get:x.bind(B,G),enumerable:!(N=f(B,G))||N.enumerable})}return _.set(B,F),F},_;var I=(B)=>B;function p(B,F){this[B]=I.bind(null,F)}var h=(B,F)=>{for(var N in F)O(B,N,{get:F[N],enumerable:!0,configurable:!0,set:p.bind(F,N)})};var n={};h(n,{resolveLineItemIdForCheckout:()=>w,createBTSCart:()=>r,catalogIdsForCartLine:()=>j,BTSCartError:()=>$,BTSCart:()=>H});module.exports=g(n);var Q="https://api.bts.it.com/v2/website/cart",A="bts-cart",R="default",z=2;function D(){try{return globalThis.window??null}catch{return null}}function Y(){try{return globalThis.localStorage??D()?.localStorage??null}catch{return null}}var y=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],k=["fbclid","gclid","gbraid","wbraid","ttclid","li_fat_id","msclkid","_fbp","_fbc"];function c(B){if(!B)return{utm:{},clickIds:{}};try{let F=JSON.parse(B);if(!F||typeof F!=="object"||Array.isArray(F))return{utm:{},clickIds:{}};let N=F,G=N.utm&&typeof N.utm==="object"&&!Array.isArray(N.utm)?Object.fromEntries(Object.entries(N.utm).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{},Z=N.clickIds&&typeof N.clickIds==="object"&&!Array.isArray(N.clickIds)?Object.fromEntries(Object.entries(N.clickIds).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{};return{utm:G,clickIds:Z}}catch{return{utm:{},clickIds:{}}}}function q(B,F){let N=new URL(B);N.searchParams.set("bts_site",F);let G=Y(),Z=G?.getItem("bts_analytics_jt")?.trim();if(Z)N.searchParams.set("bts_jt",Z);let{utm:X,clickIds:E}=c(G?.getItem("bts_analytics_attr")??null);for(let P of y){let J=X[P];if(J)N.searchParams.set(P,J)}for(let P of k){let J=E[P];if(J)N.searchParams.set(P,J)}return N.toString()}class $ extends Error{code;status;available;sold_out;quantity_exceeded;details;constructor(B,F,N,G,Z,X,E){super(F);this.name="BTSCartError",this.code=B,this.status=N,this.details=G,this.available=Z,this.sold_out=X,this.quantity_exceeded=E}}function u(){return Y()??void 0}function l(B){return(B??Q).replace(/\/$/,"")}function s(B){if(!Number.isFinite(B??1))return 1;return Math.max(1,Math.floor(B??1))}function S(B){return{items:B.map((F)=>({...F}))}}function U(B){let F=B?.trim();return F&&F.length>0?F:void 0}function w(B){return B.accessTierId??B.productId??B.lineItemId}function m(B){if(B.discountEligibleTierOrProductIds?.length)return[...new Set(B.discountEligibleTierOrProductIds.filter(Boolean))];return[...new Set([B.accessTierId,B.productId,B.lineItemId].filter((F)=>Boolean(F)))]}function C(B){let F=new Set;for(let N of B)for(let G of[N.lineItemId,N.accessTierId,N.productId])if(G)F.add(G);return B.map((N)=>{if(!N.discount)return N;let G=m(N);if(G.length===0||!G.some((Z)=>F.has(Z))){let Z={...N};return delete Z.discount,delete Z.discountEligibleTierOrProductIds,Z}return N})}function o(B,F){let N=new Headers(B);if(!F)return N;return new Headers(F).forEach((G,Z)=>N.set(Z,G)),N}function W(B){let F=B.checkoutLinkId.trim();try{let N=F.includes("://")?F:F.startsWith("/")?`https://bts-cart.invalid${F}`:F,G=new URL(N),Z=G.pathname.split("/").filter(Boolean),X=Z.indexOf("c"),E=X>=0?Z[X+1]:Z.at(-1);if(E)return{checkoutLinkId:E,discountCode:B.discountCode??G.searchParams.get("discountCode")??void 0}}catch{}return{checkoutLinkId:F,discountCode:B.discountCode}}function d(B){let F=B?.details;if(!Array.isArray(F))return;let N=F.flatMap((G)=>{if(!G||typeof G!=="object")return[];let Z=typeof G.lineItemId==="string"?G.lineItemId:"",X=typeof G.reason==="string"?G.reason:"";if(!Z||!X)return[];let E=typeof G.discountCode==="string"?G.discountCode:void 0,P=typeof G.requestedQuantity==="number"?G.requestedQuantity:void 0,J=typeof G.adjustedQuantity==="number"?G.adjustedQuantity:void 0;if(!E&&!(P!==void 0||J!==void 0||X==="line_item_sold_out"||X==="quantity_exceeded"||X==="product_unavailable"))return[];return[{lineItemId:Z,...typeof G.productId==="string"?{productId:G.productId}:{},...typeof G.accessTierId==="string"?{accessTierId:G.accessTierId}:{},...E?{discountCode:E}:{},...typeof G.discountId==="string"?{discountId:G.discountId}:{},reason:X,...P!==void 0?{requestedQuantity:P}:{},...J!==void 0?{adjustedQuantity:J}:{}}]});return N.length>0?N:void 0}var a=new Set(["discounts_invalid","quantity_invalid","cart_adjusted"]);function T(B){return a.has(B)}function j(B){return[...new Set([B.lineItemId,B.accessTierId,B.productId].filter((F)=>Boolean(F)))]}function M(B,F){let N=j(B);return[F.lineItemId,F.accessTierId,F.productId].filter((Z)=>Boolean(Z)).some((Z)=>N.includes(Z))}class H{siteKey;endpoint;debug;persist;storageKey;storage;checkoutLinks;defaultCheckoutLinkKey;requestHeaders;items=[];listeners=new Set;constructor(B){this.siteKey=B.siteKey,this.endpoint=l(B.endpoint),this.debug=B.debug??!1,this.persist=B.persist??!0,this.storageKey=B.storageKey??A,this.storage=B.storage??u(),this.checkoutLinks=B.checkoutLinks??{},this.defaultCheckoutLinkKey=B.defaultCheckoutLinkKey??Object.keys(this.checkoutLinks)[0]??R,this.requestHeaders=B.requestHeaders,this.rehydrate()}static init(B){return new H(B)}getItems(){return S(this.items).items}getState(){return S(this.items)}getItemCount(){return this.items.reduce((B,F)=>B+F.quantity,0)}getSubtotal(){return this.items.reduce((B,F)=>B+(F.fullPrice??F.unitPrice)*F.quantity,0)}getTotal(){return this.items.reduce((B,F)=>B+F.unitPrice*F.quantity,0)}subscribe(B){return this.listeners.add(B),B(this.getState()),()=>{this.listeners.delete(B)}}destroy(){this.listeners.clear()}rehydrate(){if(!this.persist||!this.storage)return;try{let B=this.storage.getItem(this.storageKey);if(!B)return;let F=JSON.parse(B);if(Array.isArray(F)||F.version!==z){this.storage.removeItem(this.storageKey);return}let N=F.items;if(!Array.isArray(N))return;this.items=C(N.map((G)=>this.normalizeItem(G)).filter((G)=>Boolean(G))),this.emit()}catch(B){this.log("Failed to hydrate cart",B)}}addItem(B){let F=this.normalizeItem(B);if(!F)return;let N=this.items.find((G)=>G.id===F.id);if(N){this.setQuantity(N.id,N.quantity+F.quantity);return}this.items=[...this.items,F],this.commit()}removeItem(B){this.items=this.items.filter((F)=>F.id!==B),this.commit()}setQuantity(B,F){let N=Math.floor(F);this.items=N<=0?this.items.filter((G)=>G.id!==B):this.items.map((G)=>G.id===B?{...G,quantity:N}:G),this.commit()}increment(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity+Math.max(1,Math.floor(F)))}decrement(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity-Math.max(1,Math.floor(F)))}clear(){if(this.items=[],this.persist&&this.storage)try{this.storage.removeItem(this.storageKey)}catch(B){this.log("Failed to clear cart storage",B)}this.emit()}removeDiscountForLineItem(B){this.items=this.items.map((F)=>{if(!M(F,{lineItemId:B,reason:"discount"}))return F;if(!F.discount)return F;let N={...F,unitPrice:F.fullPrice??F.unitPrice};return delete N.discount,delete N.discountEligibleTierOrProductIds,N}),this.commit()}async checkIfItemsAvailable(B){let F=[];for(let N of B){let G=await this.checkIfItemAvailable(this.defaultCheckoutLinkKey,N.lineItemId,N.discountId);if(G instanceof $)throw new $(G.code,G.message);F.push(G)}return F}async checkIfItemAvailable(B=this.defaultCheckoutLinkKey,F,N){let G=this.checkoutLinks[B];if(!G)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let Z=W(G),X={siteKey:this.siteKey,checkoutLinkId:Z.checkoutLinkId,mode:G.mode,lineItemId:F,...N?{discountId:N}:{}},E=await this.post("/check-availability",X);if(typeof E.ok!=="boolean")throw new $("request_failed","Availability check response was invalid.");return E}async validateCheckout(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=W(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/validate-discounts",Z);if(typeof X.ok!=="boolean")throw new $("request_failed","Cart response was invalid.");return X}catch(X){if(X instanceof $){if(T(X.code))throw this.reconcileCartAdjustments(X.details),new $(X.code,X.message,X.status,X.details);throw new $(X.code,X.message,X.status)}throw new $("request_failed","Failed to validate checkout.",void 0,void 0)}}async resolveCheckoutUrl(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=W(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/checkout-url",Z);if(X.ok!==!0||typeof X.checkoutUrl!=="string"||X.checkoutUrl.length===0)throw new $("request_failed","Cart response was invalid.");return q(X.checkoutUrl,this.siteKey)}catch(X){if(X instanceof $){if(T(X.code))throw this.reconcileCartAdjustments(X.details),new $(X.code,X.message,X.status,X.details);throw new $(X.code,X.message,X.status)}throw new $("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}async checkout(B=this.defaultCheckoutLinkKey){try{let F=await this.resolveCheckoutUrl(B),N=D();if(N)N.location.assign(F);return F}catch(F){if(F instanceof $){if(T(F.code))throw this.reconcileCartAdjustments(F.details),new $(F.code,F.message,F.status,F.details);throw new $(F.code,F.message,F.status)}throw new $("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}itemsForCheckout(B,F){if(F.mode==="static")return[];let N=this.items.filter((G)=>G.checkoutLinkKey===B).map((G)=>({lineItemId:w(G),quantity:G.quantity,...G.discount?{discount:G.discount}:{}}));if(N.length===0)throw new $("cart_empty","Your cart is empty.");return N}normalizeItem(B){let F=U(B.accessTierId),N=U(B.productId),G=U(B.lineItemId)??F??N;if(!B.id||!G||typeof B.unitPrice!=="number")return null;let Z=typeof B.name==="string"&&B.name.trim().length>0?B.name.trim():"Item";return{...B,id:B.id,lineItemId:G,...F?{accessTierId:F}:{},...N?{productId:N}:{},checkoutLinkKey:B.checkoutLinkKey??this.defaultCheckoutLinkKey,name:Z,unitPrice:B.unitPrice,quantity:s(B.quantity)}}reconcileCartAdjustments(B){if(!B?.length)return;let F=[...this.items],N=!1;for(let G of B){if(G.discountCode){F=F.map((X)=>{if(!M(X,G))return X;let E={...X,unitPrice:X.fullPrice??X.unitPrice};return delete E.discount,delete E.discountEligibleTierOrProductIds,N=!0,E});continue}if(G.reason==="line_item_sold_out"||G.reason==="product_unavailable"||G.adjustedQuantity===0){let X=F.length;if(F=F.filter((E)=>!M(E,G)),F.length!==X)N=!0;continue}if(G.reason==="quantity_exceeded"&&typeof G.adjustedQuantity==="number"&&G.adjustedQuantity>0)F=F.map((X)=>{if(!M(X,G))return X;return N=!0,{...X,quantity:G.adjustedQuantity}})}if(!N)return;this.items=F,this.commit()}async post(B,F){let N=`${this.endpoint}${B}`,G=JSON.stringify(F),Z={"Content-Type":"application/json"},X={body:F,bodyText:G,endpoint:this.endpoint,headers:Z,path:B,siteKey:this.siteKey,url:N},E=typeof this.requestHeaders==="function"?await this.requestHeaders(X):this.requestHeaders,P=o(Z,E),J=await fetch(N,{method:"POST",headers:P,body:G}),V=await J.json().catch(()=>null);if(!J.ok){let v=typeof V?.code==="string"&&V.code.length>0?V.code:"request_failed",b=typeof V?.message==="string"&&V.message.length>0?V.message:"Cart request failed";throw new $(v,b,J.status,d(V))}if(!V||typeof V!=="object")throw new $("request_failed","Cart response was invalid.",J.status);return V}commit(){if(this.items=C(this.items),this.persist&&this.storage)try{let B={version:z,items:this.items};this.storage.setItem(this.storageKey,JSON.stringify(B))}catch(B){this.log("Failed to persist cart",B)}this.emit()}emit(){let B=this.getState();for(let F of this.listeners)F(B)}log(...B){if(this.debug)console.log("[@behindthescenes/cart]",...B)}}function r(B){return H.init(B)}
|
|
1
|
+
var{defineProperty:O,getOwnPropertyNames:K,getOwnPropertyDescriptor:f}=Object,L=Object.prototype.hasOwnProperty;function x(B){return this[B]}var g=(B)=>{var F=(_??=new WeakMap).get(B),N;if(F)return F;if(F=O({},"__esModule",{value:!0}),B&&typeof B==="object"||typeof B==="function"){for(var G of K(B))if(!L.call(F,G))O(F,G,{get:x.bind(B,G),enumerable:!(N=f(B,G))||N.enumerable})}return _.set(B,F),F},_;var I=(B)=>B;function p(B,F){this[B]=I.bind(null,F)}var h=(B,F)=>{for(var N in F)O(B,N,{get:F[N],enumerable:!0,configurable:!0,set:p.bind(F,N)})};var r={};h(r,{resolveLineItemIdForCheckout:()=>w,createBTSCart:()=>n,catalogIdsForCartLine:()=>v,BTSCartError:()=>E,BTSCart:()=>H});module.exports=g(r);var A="https://api.bts.it.com/v2/website/cart",Q="bts-cart",R="default",z=2;function D(){try{return globalThis.window??null}catch{return null}}function Y(){try{return globalThis.localStorage??D()?.localStorage??null}catch{return null}}var y=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],k=["fbclid","gclid","gbraid","wbraid","ttclid","li_fat_id","msclkid","_fbp","_fbc"];function c(B){if(!B)return{utm:{},clickIds:{}};try{let F=JSON.parse(B);if(!F||typeof F!=="object"||Array.isArray(F))return{utm:{},clickIds:{}};let N=F,G=N.utm&&typeof N.utm==="object"&&!Array.isArray(N.utm)?Object.fromEntries(Object.entries(N.utm).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{},$=N.clickIds&&typeof N.clickIds==="object"&&!Array.isArray(N.clickIds)?Object.fromEntries(Object.entries(N.clickIds).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{};return{utm:G,clickIds:$}}catch{return{utm:{},clickIds:{}}}}function q(B,F){let N=new URL(B);N.searchParams.set("bts_site",F);let G=Y(),$=G?.getItem("bts_analytics_jt")?.trim();if($)N.searchParams.set("bts_jt",$);let{utm:X,clickIds:Z}=c(G?.getItem("bts_analytics_attr")??null);for(let V of y){let P=X[V];if(P)N.searchParams.set(V,P)}for(let V of k){let P=Z[V];if(P)N.searchParams.set(V,P)}return N.toString()}class E extends Error{code;status;available;sold_out;quantity_exceeded;details;constructor(B,F,N,G,$,X,Z){super(F);this.name="BTSCartError",this.code=B,this.status=N,this.details=G,this.available=$,this.sold_out=X,this.quantity_exceeded=Z}}function l(){return Y()??void 0}function u(B){return(B??A).replace(/\/$/,"")}function s(B){if(!Number.isFinite(B??1))return 1;return Math.max(1,Math.floor(B??1))}function S(B){return{items:B.map((F)=>({...F}))}}function U(B){let F=B?.trim();return F&&F.length>0?F:void 0}function w(B){return B.accessTierId??B.productId??B.lineItemId}function m(B){if(B.discountEligibleTierOrProductIds?.length)return[...new Set(B.discountEligibleTierOrProductIds.filter(Boolean))];return[...new Set([B.accessTierId,B.productId,B.lineItemId].filter((F)=>Boolean(F)))]}function C(B){let F=new Set;for(let N of B)for(let G of[N.lineItemId,N.accessTierId,N.productId])if(G)F.add(G);return B.map((N)=>{if(!N.discount)return N;let G=m(N);if(G.length===0||!G.some(($)=>F.has($))){let $={...N};return delete $.discount,delete $.discountEligibleTierOrProductIds,$}return N})}function d(B,F){let N=new Headers(B);if(!F)return N;return new Headers(F).forEach((G,$)=>N.set($,G)),N}function W(B){let F=B.checkoutLinkId.trim();try{let N=F.includes("://")?F:F.startsWith("/")?`https://bts-cart.invalid${F}`:F,G=new URL(N),$=G.pathname.split("/").filter(Boolean),X=$.indexOf("c"),Z=X>=0?$[X+1]:$.at(-1);if(Z)return{checkoutLinkId:Z,discountCode:B.discountCode??G.searchParams.get("discountCode")??void 0}}catch{}return{checkoutLinkId:F,discountCode:B.discountCode}}function a(B){let F=B?.details;if(!Array.isArray(F))return;let N=F.flatMap((G)=>{if(!G||typeof G!=="object")return[];let $=typeof G.lineItemId==="string"?G.lineItemId:"",X=typeof G.reason==="string"?G.reason:"";if(!$||!X)return[];let Z=typeof G.discountCode==="string"?G.discountCode:void 0,V=typeof G.requestedQuantity==="number"?G.requestedQuantity:void 0,P=typeof G.adjustedQuantity==="number"?G.adjustedQuantity:void 0;if(!Z&&!(V!==void 0||P!==void 0||X==="line_item_sold_out"||X==="quantity_exceeded"||X==="product_unavailable"))return[];return[{lineItemId:$,...typeof G.productId==="string"?{productId:G.productId}:{},...typeof G.accessTierId==="string"?{accessTierId:G.accessTierId}:{},...Z?{discountCode:Z}:{},...typeof G.discountId==="string"?{discountId:G.discountId}:{},reason:X,...V!==void 0?{requestedQuantity:V}:{},...P!==void 0?{adjustedQuantity:P}:{}}]});return N.length>0?N:void 0}var o=new Set(["discounts_invalid","quantity_invalid","cart_adjusted"]);function T(B){return o.has(B)}function v(B){return[...new Set([B.lineItemId,B.accessTierId,B.productId].filter((F)=>Boolean(F)))]}function M(B,F){let N=v(B);return[F.lineItemId,F.accessTierId,F.productId].filter(($)=>Boolean($)).some(($)=>N.includes($))}class H{siteKey;endpoint;debug;persist;storageKey;storage;checkoutLinks;defaultCheckoutLinkKey;requestHeaders;items=[];listeners=new Set;constructor(B){this.siteKey=B.siteKey,this.endpoint=u(B.endpoint),this.debug=B.debug??!1,this.persist=B.persist??!0,this.storageKey=B.storageKey??Q,this.storage=B.storage??l(),this.checkoutLinks=B.checkoutLinks??{},this.defaultCheckoutLinkKey=B.defaultCheckoutLinkKey??Object.keys(this.checkoutLinks)[0]??R,this.requestHeaders=B.requestHeaders,this.rehydrate()}static init(B){return new H(B)}getItems(){return S(this.items).items}getState(){return S(this.items)}getItemCount(){return this.items.reduce((B,F)=>B+F.quantity,0)}getSubtotal(){return this.items.reduce((B,F)=>B+(F.fullPrice??F.unitPrice)*F.quantity,0)}getTotal(){return this.items.reduce((B,F)=>B+F.unitPrice*F.quantity,0)}subscribe(B){return this.listeners.add(B),B(this.getState()),()=>{this.listeners.delete(B)}}destroy(){this.listeners.clear()}rehydrate(){if(!this.persist||!this.storage)return;try{let B=this.storage.getItem(this.storageKey);if(!B)return;let F=JSON.parse(B);if(Array.isArray(F)||F.version!==z){this.storage.removeItem(this.storageKey);return}let N=F.items;if(!Array.isArray(N))return;this.items=C(N.map((G)=>this.normalizeItem(G)).filter((G)=>Boolean(G))),this.emit()}catch(B){this.log("Failed to hydrate cart",B)}}addItem(B){let F=this.normalizeItem(B);if(!F)return;let N=this.items.find((G)=>G.id===F.id);if(N){this.setQuantity(N.id,N.quantity+F.quantity);return}this.items=[...this.items,F],this.commit()}removeItem(B){this.items=this.items.filter((F)=>F.id!==B),this.commit()}setQuantity(B,F){let N=Math.floor(F);this.items=N<=0?this.items.filter((G)=>G.id!==B):this.items.map((G)=>G.id===B?{...G,quantity:N}:G),this.commit()}increment(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity+Math.max(1,Math.floor(F)))}decrement(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity-Math.max(1,Math.floor(F)))}clear(){if(this.items=[],this.persist&&this.storage)try{this.storage.removeItem(this.storageKey)}catch(B){this.log("Failed to clear cart storage",B)}this.emit()}removeDiscountForLineItem(B){this.items=this.items.map((F)=>{if(!M(F,{lineItemId:B,reason:"discount"}))return F;if(!F.discount)return F;let N={...F,unitPrice:F.fullPrice??F.unitPrice};return delete N.discount,delete N.discountEligibleTierOrProductIds,N}),this.commit()}async checkIfItemsAvailable(B){let F=[];for(let N of B){let G=await this.checkIfItemAvailable(this.defaultCheckoutLinkKey,N.lineItemId,N.discountId);if(G instanceof E)throw new E(G.code,G.message);F.push(G)}return F}async checkIfItemAvailable(B=this.defaultCheckoutLinkKey,F,N){let G=this.checkoutLinks[B];if(!G)throw new E("checkout_link_not_found",`Unknown checkout link key: ${B}`);let $=W(G),X={siteKey:this.siteKey,checkoutLinkId:$.checkoutLinkId,mode:G.mode,lineItemId:F,...N?{discountId:N}:{}};try{let Z=await this.post("/check-availability",X);if(typeof Z.ok!=="boolean")throw new E("request_failed","Availability check response was invalid.");return Z}catch(Z){if(Z instanceof E){if(Z.details?.length)this.reconcileCartAdjustments(Z.details);if(Z.code==="line_item_sold_out"||Z.code==="product_unavailable"||Z.code==="quantity_exceeded")return{ok:!1,available:Z.available??!1,sold_out:Z.sold_out??Z.code==="line_item_sold_out",quantity_exceeded:Z.quantity_exceeded??(Z.code==="line_item_sold_out"||Z.code==="quantity_exceeded")}}throw Z}}async validateCheckout(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new E("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=W(F),G=this.itemsForCheckout(B,F),$={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/validate-discounts",$);if(typeof X.ok!=="boolean")throw new E("request_failed","Cart response was invalid.");return X}catch(X){if(X instanceof E){if(T(X.code))throw this.reconcileCartAdjustments(X.details),new E(X.code,X.message,X.status,X.details);throw new E(X.code,X.message,X.status)}throw new E("request_failed","Failed to validate checkout.",void 0,void 0)}}async resolveCheckoutUrl(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new E("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=W(F),G=this.itemsForCheckout(B,F),$={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/checkout-url",$);if(X.ok!==!0||typeof X.checkoutUrl!=="string"||X.checkoutUrl.length===0)throw new E("request_failed","Cart response was invalid.");return q(X.checkoutUrl,this.siteKey)}catch(X){if(X instanceof E){if(T(X.code))throw this.reconcileCartAdjustments(X.details),new E(X.code,X.message,X.status,X.details);throw new E(X.code,X.message,X.status)}throw new E("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}async checkout(B=this.defaultCheckoutLinkKey){try{let F=await this.resolveCheckoutUrl(B),N=D();if(N)N.location.assign(F);return F}catch(F){if(F instanceof E){if(T(F.code))throw this.reconcileCartAdjustments(F.details),new E(F.code,F.message,F.status,F.details);throw new E(F.code,F.message,F.status)}throw new E("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}itemsForCheckout(B,F){if(F.mode==="static")return[];let N=this.items.filter((G)=>G.checkoutLinkKey===B).map((G)=>({lineItemId:w(G),quantity:G.quantity,...G.discount?{discount:G.discount}:{}}));if(N.length===0)throw new E("cart_empty","Your cart is empty.");return N}normalizeItem(B){let F=U(B.accessTierId),N=U(B.productId),G=U(B.lineItemId)??F??N;if(!B.id||!G||typeof B.unitPrice!=="number")return null;let $=typeof B.name==="string"&&B.name.trim().length>0?B.name.trim():"Item";return{...B,id:B.id,lineItemId:G,...F?{accessTierId:F}:{},...N?{productId:N}:{},checkoutLinkKey:B.checkoutLinkKey??this.defaultCheckoutLinkKey,name:$,unitPrice:B.unitPrice,quantity:s(B.quantity)}}reconcileCartAdjustments(B){if(!B?.length)return;let F=[...this.items],N=!1;for(let G of B){if(G.discountCode){F=F.map((X)=>{if(!M(X,G))return X;let Z={...X,unitPrice:X.fullPrice??X.unitPrice};return delete Z.discount,delete Z.discountEligibleTierOrProductIds,N=!0,Z});continue}if(G.reason==="line_item_sold_out"||G.reason==="product_unavailable"||G.adjustedQuantity===0){let X=F.length;if(F=F.filter((Z)=>!M(Z,G)),F.length!==X)N=!0;continue}if(G.reason==="quantity_exceeded"&&typeof G.adjustedQuantity==="number"&&G.adjustedQuantity>0){let X=G.adjustedQuantity;F=F.map((Z)=>{if(!M(Z,G))return Z;return N=!0,{...Z,quantity:X}})}}if(!N)return;this.items=F,this.commit()}async post(B,F){let N=`${this.endpoint}${B}`,G=JSON.stringify(F),$={"Content-Type":"application/json"},X={body:F,bodyText:G,endpoint:this.endpoint,headers:$,path:B,siteKey:this.siteKey,url:N},Z=typeof this.requestHeaders==="function"?await this.requestHeaders(X):this.requestHeaders,V=d($,Z),P=await fetch(N,{method:"POST",headers:V,body:G}),J=await P.json().catch(()=>null);if(!P.ok){let b=typeof J?.code==="string"&&J.code.length>0?J.code:"request_failed",j=typeof J?.message==="string"&&J.message.length>0?J.message:"Cart request failed";throw new E(b,j,P.status,a(J),typeof J?.available==="boolean"?J.available:void 0,typeof J?.sold_out==="boolean"?J.sold_out:void 0,typeof J?.quantity_exceeded==="boolean"?J.quantity_exceeded:void 0)}if(!J||typeof J!=="object")throw new E("request_failed","Cart response was invalid.",P.status);return J}commit(){if(this.items=C(this.items),this.persist&&this.storage)try{let B={version:z,items:this.items};this.storage.setItem(this.storageKey,JSON.stringify(B))}catch(B){this.log("Failed to persist cart",B)}this.emit()}emit(){let B=this.getState();for(let F of this.listeners)F(B)}log(...B){if(this.debug)console.log("[@behindthescenes/cart]",...B)}}function n(B){return H.init(B)}
|
package/dist/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var T="https://api.bts.it.com/v2/website/cart",_="bts-cart",Q="default",H=2;function O(){try{return globalThis.window??null}catch{return null}}function Y(){try{return globalThis.localStorage??O()?.localStorage??null}catch{return null}}var w=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],j=["fbclid","gclid","gbraid","wbraid","ttclid","li_fat_id","msclkid","_fbp","_fbc"];function v(B){if(!B)return{utm:{},clickIds:{}};try{let F=JSON.parse(B);if(!F||typeof F!=="object"||Array.isArray(F))return{utm:{},clickIds:{}};let N=F,G=N.utm&&typeof N.utm==="object"&&!Array.isArray(N.utm)?Object.fromEntries(Object.entries(N.utm).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{},Z=N.clickIds&&typeof N.clickIds==="object"&&!Array.isArray(N.clickIds)?Object.fromEntries(Object.entries(N.clickIds).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{};return{utm:G,clickIds:Z}}catch{return{utm:{},clickIds:{}}}}function A(B,F){let N=new URL(B);N.searchParams.set("bts_site",F);let G=Y(),Z=G?.getItem("bts_analytics_jt")?.trim();if(Z)N.searchParams.set("bts_jt",Z);let{utm:X,clickIds:E}=v(G?.getItem("bts_analytics_attr")??null);for(let P of w){let J=X[P];if(J)N.searchParams.set(P,J)}for(let P of j){let J=E[P];if(J)N.searchParams.set(P,J)}return N.toString()}class $ extends Error{code;status;available;sold_out;quantity_exceeded;details;constructor(B,F,N,G,Z,X,E){super(F);this.name="BTSCartError",this.code=B,this.status=N,this.details=G,this.available=Z,this.sold_out=X,this.quantity_exceeded=E}}function b(){return Y()??void 0}function K(B){return(B??T).replace(/\/$/,"")}function f(B){if(!Number.isFinite(B??1))return 1;return Math.max(1,Math.floor(B??1))}function R(B){return{items:B.map((F)=>({...F}))}}function z(B){let F=B?.trim();return F&&F.length>0?F:void 0}function L(B){return B.accessTierId??B.productId??B.lineItemId}function x(B){if(B.discountEligibleTierOrProductIds?.length)return[...new Set(B.discountEligibleTierOrProductIds.filter(Boolean))];return[...new Set([B.accessTierId,B.productId,B.lineItemId].filter((F)=>Boolean(F)))]}function q(B){let F=new Set;for(let N of B)for(let G of[N.lineItemId,N.accessTierId,N.productId])if(G)F.add(G);return B.map((N)=>{if(!N.discount)return N;let G=x(N);if(G.length===0||!G.some((Z)=>F.has(Z))){let Z={...N};return delete Z.discount,delete Z.discountEligibleTierOrProductIds,Z}return N})}function g(B,F){let N=new Headers(B);if(!F)return N;return new Headers(F).forEach((G,Z)=>N.set(Z,G)),N}function D(B){let F=B.checkoutLinkId.trim();try{let N=F.includes("://")?F:F.startsWith("/")?`https://bts-cart.invalid${F}`:F,G=new URL(N),Z=G.pathname.split("/").filter(Boolean),X=Z.indexOf("c"),E=X>=0?Z[X+1]:Z.at(-1);if(E)return{checkoutLinkId:E,discountCode:B.discountCode??G.searchParams.get("discountCode")??void 0}}catch{}return{checkoutLinkId:F,discountCode:B.discountCode}}function I(B){let F=B?.details;if(!Array.isArray(F))return;let N=F.flatMap((G)=>{if(!G||typeof G!=="object")return[];let Z=typeof G.lineItemId==="string"?G.lineItemId:"",X=typeof G.reason==="string"?G.reason:"";if(!Z||!X)return[];let E=typeof G.discountCode==="string"?G.discountCode:void 0,P=typeof G.requestedQuantity==="number"?G.requestedQuantity:void 0,J=typeof G.adjustedQuantity==="number"?G.adjustedQuantity:void 0;if(!E&&!(P!==void 0||J!==void 0||X==="line_item_sold_out"||X==="quantity_exceeded"||X==="product_unavailable"))return[];return[{lineItemId:Z,...typeof G.productId==="string"?{productId:G.productId}:{},...typeof G.accessTierId==="string"?{accessTierId:G.accessTierId}:{},...E?{discountCode:E}:{},...typeof G.discountId==="string"?{discountId:G.discountId}:{},reason:X,...P!==void 0?{requestedQuantity:P}:{},...J!==void 0?{adjustedQuantity:J}:{}}]});return N.length>0?N:void 0}var p=new Set(["discounts_invalid","quantity_invalid","cart_adjusted"]);function U(B){return p.has(B)}function h(B){return[...new Set([B.lineItemId,B.accessTierId,B.productId].filter((F)=>Boolean(F)))]}function M(B,F){let N=h(B);return[F.lineItemId,F.accessTierId,F.productId].filter((Z)=>Boolean(Z)).some((Z)=>N.includes(Z))}class W{siteKey;endpoint;debug;persist;storageKey;storage;checkoutLinks;defaultCheckoutLinkKey;requestHeaders;items=[];listeners=new Set;constructor(B){this.siteKey=B.siteKey,this.endpoint=K(B.endpoint),this.debug=B.debug??!1,this.persist=B.persist??!0,this.storageKey=B.storageKey??_,this.storage=B.storage??b(),this.checkoutLinks=B.checkoutLinks??{},this.defaultCheckoutLinkKey=B.defaultCheckoutLinkKey??Object.keys(this.checkoutLinks)[0]??Q,this.requestHeaders=B.requestHeaders,this.rehydrate()}static init(B){return new W(B)}getItems(){return R(this.items).items}getState(){return R(this.items)}getItemCount(){return this.items.reduce((B,F)=>B+F.quantity,0)}getSubtotal(){return this.items.reduce((B,F)=>B+(F.fullPrice??F.unitPrice)*F.quantity,0)}getTotal(){return this.items.reduce((B,F)=>B+F.unitPrice*F.quantity,0)}subscribe(B){return this.listeners.add(B),B(this.getState()),()=>{this.listeners.delete(B)}}destroy(){this.listeners.clear()}rehydrate(){if(!this.persist||!this.storage)return;try{let B=this.storage.getItem(this.storageKey);if(!B)return;let F=JSON.parse(B);if(Array.isArray(F)||F.version!==H){this.storage.removeItem(this.storageKey);return}let N=F.items;if(!Array.isArray(N))return;this.items=q(N.map((G)=>this.normalizeItem(G)).filter((G)=>Boolean(G))),this.emit()}catch(B){this.log("Failed to hydrate cart",B)}}addItem(B){let F=this.normalizeItem(B);if(!F)return;let N=this.items.find((G)=>G.id===F.id);if(N){this.setQuantity(N.id,N.quantity+F.quantity);return}this.items=[...this.items,F],this.commit()}removeItem(B){this.items=this.items.filter((F)=>F.id!==B),this.commit()}setQuantity(B,F){let N=Math.floor(F);this.items=N<=0?this.items.filter((G)=>G.id!==B):this.items.map((G)=>G.id===B?{...G,quantity:N}:G),this.commit()}increment(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity+Math.max(1,Math.floor(F)))}decrement(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity-Math.max(1,Math.floor(F)))}clear(){if(this.items=[],this.persist&&this.storage)try{this.storage.removeItem(this.storageKey)}catch(B){this.log("Failed to clear cart storage",B)}this.emit()}removeDiscountForLineItem(B){this.items=this.items.map((F)=>{if(!M(F,{lineItemId:B,reason:"discount"}))return F;if(!F.discount)return F;let N={...F,unitPrice:F.fullPrice??F.unitPrice};return delete N.discount,delete N.discountEligibleTierOrProductIds,N}),this.commit()}async checkIfItemsAvailable(B){let F=[];for(let N of B){let G=await this.checkIfItemAvailable(this.defaultCheckoutLinkKey,N.lineItemId,N.discountId);if(G instanceof $)throw new $(G.code,G.message);F.push(G)}return F}async checkIfItemAvailable(B=this.defaultCheckoutLinkKey,F,N){let G=this.checkoutLinks[B];if(!G)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let Z=D(G),X={siteKey:this.siteKey,checkoutLinkId:Z.checkoutLinkId,mode:G.mode,lineItemId:F,...N?{discountId:N}:{}},E=await this.post("/check-availability",X);if(typeof E.ok!=="boolean")throw new $("request_failed","Availability check response was invalid.");return E}async validateCheckout(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=D(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/validate-discounts",Z);if(typeof X.ok!=="boolean")throw new $("request_failed","Cart response was invalid.");return X}catch(X){if(X instanceof $){if(U(X.code))throw this.reconcileCartAdjustments(X.details),new $(X.code,X.message,X.status,X.details);throw new $(X.code,X.message,X.status)}throw new $("request_failed","Failed to validate checkout.",void 0,void 0)}}async resolveCheckoutUrl(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new $("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=D(F),G=this.itemsForCheckout(B,F),Z={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/checkout-url",Z);if(X.ok!==!0||typeof X.checkoutUrl!=="string"||X.checkoutUrl.length===0)throw new $("request_failed","Cart response was invalid.");return A(X.checkoutUrl,this.siteKey)}catch(X){if(X instanceof $){if(U(X.code))throw this.reconcileCartAdjustments(X.details),new $(X.code,X.message,X.status,X.details);throw new $(X.code,X.message,X.status)}throw new $("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}async checkout(B=this.defaultCheckoutLinkKey){try{let F=await this.resolveCheckoutUrl(B),N=O();if(N)N.location.assign(F);return F}catch(F){if(F instanceof $){if(U(F.code))throw this.reconcileCartAdjustments(F.details),new $(F.code,F.message,F.status,F.details);throw new $(F.code,F.message,F.status)}throw new $("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}itemsForCheckout(B,F){if(F.mode==="static")return[];let N=this.items.filter((G)=>G.checkoutLinkKey===B).map((G)=>({lineItemId:L(G),quantity:G.quantity,...G.discount?{discount:G.discount}:{}}));if(N.length===0)throw new $("cart_empty","Your cart is empty.");return N}normalizeItem(B){let F=z(B.accessTierId),N=z(B.productId),G=z(B.lineItemId)??F??N;if(!B.id||!G||typeof B.unitPrice!=="number")return null;let Z=typeof B.name==="string"&&B.name.trim().length>0?B.name.trim():"Item";return{...B,id:B.id,lineItemId:G,...F?{accessTierId:F}:{},...N?{productId:N}:{},checkoutLinkKey:B.checkoutLinkKey??this.defaultCheckoutLinkKey,name:Z,unitPrice:B.unitPrice,quantity:f(B.quantity)}}reconcileCartAdjustments(B){if(!B?.length)return;let F=[...this.items],N=!1;for(let G of B){if(G.discountCode){F=F.map((X)=>{if(!M(X,G))return X;let E={...X,unitPrice:X.fullPrice??X.unitPrice};return delete E.discount,delete E.discountEligibleTierOrProductIds,N=!0,E});continue}if(G.reason==="line_item_sold_out"||G.reason==="product_unavailable"||G.adjustedQuantity===0){let X=F.length;if(F=F.filter((E)=>!M(E,G)),F.length!==X)N=!0;continue}if(G.reason==="quantity_exceeded"&&typeof G.adjustedQuantity==="number"&&G.adjustedQuantity>0)F=F.map((X)=>{if(!M(X,G))return X;return N=!0,{...X,quantity:G.adjustedQuantity}})}if(!N)return;this.items=F,this.commit()}async post(B,F){let N=`${this.endpoint}${B}`,G=JSON.stringify(F),Z={"Content-Type":"application/json"},X={body:F,bodyText:G,endpoint:this.endpoint,headers:Z,path:B,siteKey:this.siteKey,url:N},E=typeof this.requestHeaders==="function"?await this.requestHeaders(X):this.requestHeaders,P=g(Z,E),J=await fetch(N,{method:"POST",headers:P,body:G}),V=await J.json().catch(()=>null);if(!J.ok){let S=typeof V?.code==="string"&&V.code.length>0?V.code:"request_failed",C=typeof V?.message==="string"&&V.message.length>0?V.message:"Cart request failed";throw new $(S,C,J.status,I(V))}if(!V||typeof V!=="object")throw new $("request_failed","Cart response was invalid.",J.status);return V}commit(){if(this.items=q(this.items),this.persist&&this.storage)try{let B={version:H,items:this.items};this.storage.setItem(this.storageKey,JSON.stringify(B))}catch(B){this.log("Failed to persist cart",B)}this.emit()}emit(){let B=this.getState();for(let F of this.listeners)F(B)}log(...B){if(this.debug)console.log("[@behindthescenes/cart]",...B)}}function n(B){return W.init(B)}export{L as resolveLineItemIdForCheckout,n as createBTSCart,h as catalogIdsForCartLine,$ as BTSCartError,W as BTSCart};
|
|
1
|
+
var T="https://api.bts.it.com/v2/website/cart",_="bts-cart",A="default",H=2;function O(){try{return globalThis.window??null}catch{return null}}function Y(){try{return globalThis.localStorage??O()?.localStorage??null}catch{return null}}var w=["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],v=["fbclid","gclid","gbraid","wbraid","ttclid","li_fat_id","msclkid","_fbp","_fbc"];function b(B){if(!B)return{utm:{},clickIds:{}};try{let F=JSON.parse(B);if(!F||typeof F!=="object"||Array.isArray(F))return{utm:{},clickIds:{}};let N=F,G=N.utm&&typeof N.utm==="object"&&!Array.isArray(N.utm)?Object.fromEntries(Object.entries(N.utm).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{},$=N.clickIds&&typeof N.clickIds==="object"&&!Array.isArray(N.clickIds)?Object.fromEntries(Object.entries(N.clickIds).filter((X)=>typeof X[1]==="string"&&X[1].length>0)):{};return{utm:G,clickIds:$}}catch{return{utm:{},clickIds:{}}}}function Q(B,F){let N=new URL(B);N.searchParams.set("bts_site",F);let G=Y(),$=G?.getItem("bts_analytics_jt")?.trim();if($)N.searchParams.set("bts_jt",$);let{utm:X,clickIds:Z}=b(G?.getItem("bts_analytics_attr")??null);for(let V of w){let P=X[V];if(P)N.searchParams.set(V,P)}for(let V of v){let P=Z[V];if(P)N.searchParams.set(V,P)}return N.toString()}class E extends Error{code;status;available;sold_out;quantity_exceeded;details;constructor(B,F,N,G,$,X,Z){super(F);this.name="BTSCartError",this.code=B,this.status=N,this.details=G,this.available=$,this.sold_out=X,this.quantity_exceeded=Z}}function j(){return Y()??void 0}function K(B){return(B??T).replace(/\/$/,"")}function f(B){if(!Number.isFinite(B??1))return 1;return Math.max(1,Math.floor(B??1))}function R(B){return{items:B.map((F)=>({...F}))}}function z(B){let F=B?.trim();return F&&F.length>0?F:void 0}function L(B){return B.accessTierId??B.productId??B.lineItemId}function x(B){if(B.discountEligibleTierOrProductIds?.length)return[...new Set(B.discountEligibleTierOrProductIds.filter(Boolean))];return[...new Set([B.accessTierId,B.productId,B.lineItemId].filter((F)=>Boolean(F)))]}function q(B){let F=new Set;for(let N of B)for(let G of[N.lineItemId,N.accessTierId,N.productId])if(G)F.add(G);return B.map((N)=>{if(!N.discount)return N;let G=x(N);if(G.length===0||!G.some(($)=>F.has($))){let $={...N};return delete $.discount,delete $.discountEligibleTierOrProductIds,$}return N})}function g(B,F){let N=new Headers(B);if(!F)return N;return new Headers(F).forEach((G,$)=>N.set($,G)),N}function D(B){let F=B.checkoutLinkId.trim();try{let N=F.includes("://")?F:F.startsWith("/")?`https://bts-cart.invalid${F}`:F,G=new URL(N),$=G.pathname.split("/").filter(Boolean),X=$.indexOf("c"),Z=X>=0?$[X+1]:$.at(-1);if(Z)return{checkoutLinkId:Z,discountCode:B.discountCode??G.searchParams.get("discountCode")??void 0}}catch{}return{checkoutLinkId:F,discountCode:B.discountCode}}function I(B){let F=B?.details;if(!Array.isArray(F))return;let N=F.flatMap((G)=>{if(!G||typeof G!=="object")return[];let $=typeof G.lineItemId==="string"?G.lineItemId:"",X=typeof G.reason==="string"?G.reason:"";if(!$||!X)return[];let Z=typeof G.discountCode==="string"?G.discountCode:void 0,V=typeof G.requestedQuantity==="number"?G.requestedQuantity:void 0,P=typeof G.adjustedQuantity==="number"?G.adjustedQuantity:void 0;if(!Z&&!(V!==void 0||P!==void 0||X==="line_item_sold_out"||X==="quantity_exceeded"||X==="product_unavailable"))return[];return[{lineItemId:$,...typeof G.productId==="string"?{productId:G.productId}:{},...typeof G.accessTierId==="string"?{accessTierId:G.accessTierId}:{},...Z?{discountCode:Z}:{},...typeof G.discountId==="string"?{discountId:G.discountId}:{},reason:X,...V!==void 0?{requestedQuantity:V}:{},...P!==void 0?{adjustedQuantity:P}:{}}]});return N.length>0?N:void 0}var p=new Set(["discounts_invalid","quantity_invalid","cart_adjusted"]);function U(B){return p.has(B)}function h(B){return[...new Set([B.lineItemId,B.accessTierId,B.productId].filter((F)=>Boolean(F)))]}function M(B,F){let N=h(B);return[F.lineItemId,F.accessTierId,F.productId].filter(($)=>Boolean($)).some(($)=>N.includes($))}class W{siteKey;endpoint;debug;persist;storageKey;storage;checkoutLinks;defaultCheckoutLinkKey;requestHeaders;items=[];listeners=new Set;constructor(B){this.siteKey=B.siteKey,this.endpoint=K(B.endpoint),this.debug=B.debug??!1,this.persist=B.persist??!0,this.storageKey=B.storageKey??_,this.storage=B.storage??j(),this.checkoutLinks=B.checkoutLinks??{},this.defaultCheckoutLinkKey=B.defaultCheckoutLinkKey??Object.keys(this.checkoutLinks)[0]??A,this.requestHeaders=B.requestHeaders,this.rehydrate()}static init(B){return new W(B)}getItems(){return R(this.items).items}getState(){return R(this.items)}getItemCount(){return this.items.reduce((B,F)=>B+F.quantity,0)}getSubtotal(){return this.items.reduce((B,F)=>B+(F.fullPrice??F.unitPrice)*F.quantity,0)}getTotal(){return this.items.reduce((B,F)=>B+F.unitPrice*F.quantity,0)}subscribe(B){return this.listeners.add(B),B(this.getState()),()=>{this.listeners.delete(B)}}destroy(){this.listeners.clear()}rehydrate(){if(!this.persist||!this.storage)return;try{let B=this.storage.getItem(this.storageKey);if(!B)return;let F=JSON.parse(B);if(Array.isArray(F)||F.version!==H){this.storage.removeItem(this.storageKey);return}let N=F.items;if(!Array.isArray(N))return;this.items=q(N.map((G)=>this.normalizeItem(G)).filter((G)=>Boolean(G))),this.emit()}catch(B){this.log("Failed to hydrate cart",B)}}addItem(B){let F=this.normalizeItem(B);if(!F)return;let N=this.items.find((G)=>G.id===F.id);if(N){this.setQuantity(N.id,N.quantity+F.quantity);return}this.items=[...this.items,F],this.commit()}removeItem(B){this.items=this.items.filter((F)=>F.id!==B),this.commit()}setQuantity(B,F){let N=Math.floor(F);this.items=N<=0?this.items.filter((G)=>G.id!==B):this.items.map((G)=>G.id===B?{...G,quantity:N}:G),this.commit()}increment(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity+Math.max(1,Math.floor(F)))}decrement(B,F=1){let N=this.items.find((G)=>G.id===B);if(N)this.setQuantity(B,N.quantity-Math.max(1,Math.floor(F)))}clear(){if(this.items=[],this.persist&&this.storage)try{this.storage.removeItem(this.storageKey)}catch(B){this.log("Failed to clear cart storage",B)}this.emit()}removeDiscountForLineItem(B){this.items=this.items.map((F)=>{if(!M(F,{lineItemId:B,reason:"discount"}))return F;if(!F.discount)return F;let N={...F,unitPrice:F.fullPrice??F.unitPrice};return delete N.discount,delete N.discountEligibleTierOrProductIds,N}),this.commit()}async checkIfItemsAvailable(B){let F=[];for(let N of B){let G=await this.checkIfItemAvailable(this.defaultCheckoutLinkKey,N.lineItemId,N.discountId);if(G instanceof E)throw new E(G.code,G.message);F.push(G)}return F}async checkIfItemAvailable(B=this.defaultCheckoutLinkKey,F,N){let G=this.checkoutLinks[B];if(!G)throw new E("checkout_link_not_found",`Unknown checkout link key: ${B}`);let $=D(G),X={siteKey:this.siteKey,checkoutLinkId:$.checkoutLinkId,mode:G.mode,lineItemId:F,...N?{discountId:N}:{}};try{let Z=await this.post("/check-availability",X);if(typeof Z.ok!=="boolean")throw new E("request_failed","Availability check response was invalid.");return Z}catch(Z){if(Z instanceof E){if(Z.details?.length)this.reconcileCartAdjustments(Z.details);if(Z.code==="line_item_sold_out"||Z.code==="product_unavailable"||Z.code==="quantity_exceeded")return{ok:!1,available:Z.available??!1,sold_out:Z.sold_out??Z.code==="line_item_sold_out",quantity_exceeded:Z.quantity_exceeded??(Z.code==="line_item_sold_out"||Z.code==="quantity_exceeded")}}throw Z}}async validateCheckout(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new E("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=D(F),G=this.itemsForCheckout(B,F),$={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/validate-discounts",$);if(typeof X.ok!=="boolean")throw new E("request_failed","Cart response was invalid.");return X}catch(X){if(X instanceof E){if(U(X.code))throw this.reconcileCartAdjustments(X.details),new E(X.code,X.message,X.status,X.details);throw new E(X.code,X.message,X.status)}throw new E("request_failed","Failed to validate checkout.",void 0,void 0)}}async resolveCheckoutUrl(B=this.defaultCheckoutLinkKey){let F=this.checkoutLinks[B];if(!F)throw new E("checkout_link_not_found",`Unknown checkout link key: ${B}`);let N=D(F),G=this.itemsForCheckout(B,F),$={siteKey:this.siteKey,checkoutLinkId:N.checkoutLinkId,mode:F.mode,...N.discountCode?{discountCode:N.discountCode}:{},...G.length>0?{items:G}:{}};try{let X=await this.post("/checkout-url",$);if(X.ok!==!0||typeof X.checkoutUrl!=="string"||X.checkoutUrl.length===0)throw new E("request_failed","Cart response was invalid.");return Q(X.checkoutUrl,this.siteKey)}catch(X){if(X instanceof E){if(U(X.code))throw this.reconcileCartAdjustments(X.details),new E(X.code,X.message,X.status,X.details);throw new E(X.code,X.message,X.status)}throw new E("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}async checkout(B=this.defaultCheckoutLinkKey){try{let F=await this.resolveCheckoutUrl(B),N=O();if(N)N.location.assign(F);return F}catch(F){if(F instanceof E){if(U(F.code))throw this.reconcileCartAdjustments(F.details),new E(F.code,F.message,F.status,F.details);throw new E(F.code,F.message,F.status)}throw new E("request_failed","Failed to resolve checkout URL.",void 0,void 0)}}itemsForCheckout(B,F){if(F.mode==="static")return[];let N=this.items.filter((G)=>G.checkoutLinkKey===B).map((G)=>({lineItemId:L(G),quantity:G.quantity,...G.discount?{discount:G.discount}:{}}));if(N.length===0)throw new E("cart_empty","Your cart is empty.");return N}normalizeItem(B){let F=z(B.accessTierId),N=z(B.productId),G=z(B.lineItemId)??F??N;if(!B.id||!G||typeof B.unitPrice!=="number")return null;let $=typeof B.name==="string"&&B.name.trim().length>0?B.name.trim():"Item";return{...B,id:B.id,lineItemId:G,...F?{accessTierId:F}:{},...N?{productId:N}:{},checkoutLinkKey:B.checkoutLinkKey??this.defaultCheckoutLinkKey,name:$,unitPrice:B.unitPrice,quantity:f(B.quantity)}}reconcileCartAdjustments(B){if(!B?.length)return;let F=[...this.items],N=!1;for(let G of B){if(G.discountCode){F=F.map((X)=>{if(!M(X,G))return X;let Z={...X,unitPrice:X.fullPrice??X.unitPrice};return delete Z.discount,delete Z.discountEligibleTierOrProductIds,N=!0,Z});continue}if(G.reason==="line_item_sold_out"||G.reason==="product_unavailable"||G.adjustedQuantity===0){let X=F.length;if(F=F.filter((Z)=>!M(Z,G)),F.length!==X)N=!0;continue}if(G.reason==="quantity_exceeded"&&typeof G.adjustedQuantity==="number"&&G.adjustedQuantity>0){let X=G.adjustedQuantity;F=F.map((Z)=>{if(!M(Z,G))return Z;return N=!0,{...Z,quantity:X}})}}if(!N)return;this.items=F,this.commit()}async post(B,F){let N=`${this.endpoint}${B}`,G=JSON.stringify(F),$={"Content-Type":"application/json"},X={body:F,bodyText:G,endpoint:this.endpoint,headers:$,path:B,siteKey:this.siteKey,url:N},Z=typeof this.requestHeaders==="function"?await this.requestHeaders(X):this.requestHeaders,V=g($,Z),P=await fetch(N,{method:"POST",headers:V,body:G}),J=await P.json().catch(()=>null);if(!P.ok){let S=typeof J?.code==="string"&&J.code.length>0?J.code:"request_failed",C=typeof J?.message==="string"&&J.message.length>0?J.message:"Cart request failed";throw new E(S,C,P.status,I(J),typeof J?.available==="boolean"?J.available:void 0,typeof J?.sold_out==="boolean"?J.sold_out:void 0,typeof J?.quantity_exceeded==="boolean"?J.quantity_exceeded:void 0)}if(!J||typeof J!=="object")throw new E("request_failed","Cart response was invalid.",P.status);return J}commit(){if(this.items=q(this.items),this.persist&&this.storage)try{let B={version:H,items:this.items};this.storage.setItem(this.storageKey,JSON.stringify(B))}catch(B){this.log("Failed to persist cart",B)}this.emit()}emit(){let B=this.getState();for(let F of this.listeners)F(B)}log(...B){if(this.debug)console.log("[@behindthescenes/cart]",...B)}}function r(B){return W.init(B)}export{L as resolveLineItemIdForCheckout,r as createBTSCart,h as catalogIdsForCartLine,E as BTSCartError,W as BTSCart};
|
package/dist/manifest.json
CHANGED