@shopify/hydrogen
Version:
<div align="center">
412 lines (409 loc) • 89.7 kB
JavaScript
import {createContext,forwardRef,useContext,lazy,useMemo,useEffect,useRef,useState,createElement,Fragment as Fragment$1,Suspense}from'react';import {useFetcher,useFetchers,useNavigation,useLocation,useNavigate,Link,useMatches}from'@remix-run/react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {useLoadScript,createStorefrontClient,SHOPIFY_STOREFRONT_ID_HEADER,getShopifyCookies,SHOPIFY_Y,SHOPIFY_STOREFRONT_Y_HEADER,SHOPIFY_S,SHOPIFY_STOREFRONT_S_HEADER,flattenConnection,RichText,ShopPayButton,useShopifyCookies,parseGid,sendShopifyAnalytics,AnalyticsEventName,AnalyticsPageType,getClientBrowserParameters}from'@shopify/hydrogen-react';export{AnalyticsEventName,AnalyticsPageType,ExternalVideo,IMAGE_FRAGMENT,Image,MediaFile,ModelViewer,Money,ShopifySalesChannel,Video,customerAccountApiCustomScalars,decodeEncodedVariant,flattenConnection,getAdjacentAndFirstAvailableVariants,getClientBrowserParameters,getProductOptions,getShopifyCookies,isOptionValueCombinationInEncodedVariant,mapSelectedProductOptionToObject,parseGid,parseMetafield,sendShopifyAnalytics,storefrontApiCustomScalars,useLoadScript,useMoney,useSelectedOptionInUrlParam,useShopifyCookies}from'@shopify/hydrogen-react';import {parse,stringify}from'worktop/cookie';import da from'content-security-policy-builder';function ue(e){let{type:t,data:r={},customData:n}=e,o=useLocation(),{publish:a,cart:i,prevCart:c,shop:s,customData:u}=B(),p=o.pathname+o.search,l={...r,customData:{...u,...n},cart:i,prevCart:c,shop:s};return useEffect(()=>{s?.shopId&&(l={...l,url:window.location.href},a(t,l));},[a,p,s?.shopId]),null}function Xt(e){return jsx(ue,{...e,type:"page_viewed"})}function Zt(e){return jsx(ue,{...e,type:"product_viewed"})}function er(e){return jsx(ue,{...e,type:"collection_viewed"})}function tr(e){return jsx(ue,{...e,type:"cart_viewed"})}function rr(e){return jsx(ue,{...e,type:"search_viewed"})}function or(e){return jsx(ue,{...e})}var V={PAGE_VIEWED:"page_viewed",PRODUCT_VIEWED:"product_viewed",COLLECTION_VIEWED:"collection_viewed",CART_VIEWED:"cart_viewed",SEARCH_VIEWED:"search_viewed",CART_UPDATED:"cart_updated",PRODUCT_ADD_TO_CART:"product_added_to_cart",PRODUCT_REMOVED_FROM_CART:"product_removed_from_cart",CUSTOM_EVENT:"custom_"};var Eo="https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.1/consent-tracking-api.js",wo="https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js";function rt(e){console.error(`[h2:error:useCustomerPrivacy] Unable to setup Customer Privacy API: Missing consent.${e} configuration.`);}function ot(e){let{withPrivacyBanner:t=false,onVisitorConsentCollected:r,onReady:n,...o}=e;useLoadScript(t?wo:Eo,{attributes:{id:"customer-privacy-api"}});let{observing:a,setLoaded:i}=bo({withPrivacyBanner:t,onLoaded:n}),c=useMemo(()=>{let{checkoutDomain:u,storefrontAccessToken:p}=o;return u||rt("checkoutDomain"),p||rt("storefrontAccessToken"),(p.startsWith("shpat_")||p.length!==32)&&console.error("[h2:error:useCustomerPrivacy] It looks like you passed a private access token, make sure to use the public token"),{checkoutRootDomain:u,storefrontAccessToken:p,storefrontRootDomain:ir(u),country:o.country,locale:o.locale}},[o,ir,rt]);useEffect(()=>{let u=p=>{r&&r(p.detail);};return document.addEventListener("visitorConsentCollected",u),()=>{document.removeEventListener("visitorConsentCollected",u);}},[r]),useEffect(()=>{if(!t||a.current.privacyBanner)return;a.current.privacyBanner=true;let u=window.privacyBanner||void 0;Object.defineProperty(window,"privacyBanner",{configurable:true,get(){return u},set(l){if(typeof l=="object"&&l!==null&&"showPreferences"in l&&"loadBanner"in l){let m=l;m.loadBanner(c),u=cr({privacyBanner:m,config:c}),i.privacyBanner(),ar();}}});},[t,c,cr,i.privacyBanner]),useEffect(()=>{if(a.current.customerPrivacy)return;a.current.customerPrivacy=true;let u=null,p=window.Shopify||void 0;Object.defineProperty(window,"Shopify",{configurable:true,get(){return p},set(l){typeof l=="object"&&l!==null&&Object.keys(l).length===0&&(p=l,Object.defineProperty(window.Shopify,"customerPrivacy",{configurable:true,get(){return u},set(m){if(typeof m=="object"&&m!==null&&"setTrackingConsent"in m){let y=m;u={...y,setTrackingConsent:sr({customerPrivacy:y,config:c})},p={...p,customerPrivacy:u},i.customerPrivacy(),ar();}}}));}});},[c,sr,i.customerPrivacy]);let s={customerPrivacy:de()};return t&&(s.privacyBanner=Le()),s}var nr=false;function ar(){if(nr)return;nr=true;let e=new CustomEvent("shopifyCustomerPrivacyApiLoaded");document.dispatchEvent(e);}function bo({withPrivacyBanner:e,onLoaded:t}){let r=useRef({customerPrivacy:false,privacyBanner:false}),[n,o]=useState(e?[false,false]:[false]),a=n.every(Boolean),i={customerPrivacy:()=>{o(e?c=>[true,c[1]]:()=>[true]);},privacyBanner:()=>{e&&o(c=>[c[0],true]);}};return useEffect(()=>{a&&t&&t();},[a,t]),{observing:r,setLoaded:i}}function ir(e){if(typeof window>"u")return;let t=window.document.location.host,r=e.split(".").reverse(),n=t.split(".").reverse(),o=[];return r.forEach((a,i)=>{a===n[i]&&o.push(a);}),o.reverse().join(".")}function sr({customerPrivacy:e,config:t}){let r=e.setTrackingConsent,{locale:n,country:o,...a}=t;function i(c,s){r({...a,headlessStorefront:true,...c},s);}return i}function cr({privacyBanner:e,config:t}){let r=e.loadBanner,n=e.showPreferences;function o(i){if(typeof i=="object"){r({...t,...i});return}r(t);}function a(i){if(typeof i=="object"){n({...t,...i});return}n(t);}return {loadBanner:o,showPreferences:a}}function de(){try{return window.Shopify&&window.Shopify.customerPrivacy?window.Shopify?.customerPrivacy:null}catch{return null}}function Le(){try{return window&&window?.privacyBanner?window.privacyBanner:null}catch{return null}}var ur="2025.1.3";function Uo(){let e=de();if(!e)throw new Error("Shopify Customer Privacy API not available. Must be used within a useEffect. Make sure to load the Shopify Customer Privacy API with useCustomerPrivacy() or <AnalyticsProvider>.");return e}function lr({consent:e,onReady:t,domain:r}){let{subscribe:n,register:o,canTrack:a}=B(),[i,c]=useState(false),[s,u]=useState(false),p=useRef(false),{checkoutDomain:l,storefrontAccessToken:m,language:y}=e,{ready:d}=o("Internal_Shopify_Analytics");return ot({...e,locale:y,checkoutDomain:l||"mock.shop",storefrontAccessToken:m||"abcdefghijklmnopqrstuvwxyz123456",onVisitorConsentCollected:()=>u(true),onReady:()=>u(true)}),useShopifyCookies({hasUserConsent:s?a():true,domain:r,checkoutDomain:l}),useEffect(()=>{p.current||(p.current=true,n(V.PAGE_VIEWED,ko),n(V.PRODUCT_VIEWED,No),n(V.COLLECTION_VIEWED,Vo),n(V.SEARCH_VIEWED,Mo),n(V.PRODUCT_ADD_TO_CART,qo),c(true));},[n]),useEffect(()=>{i&&s&&(d(),t());},[i,s,t]),null}function ke(e){console.error(`[h2:error:ShopifyAnalytics] Unable to send Shopify analytics: Missing shop.${e} configuration.`);}function Ae(e){let t=Uo(),r=t.analyticsProcessingAllowed();if(!e?.shop?.shopId){ke("shopId");return}if(!e?.shop?.acceptedLanguage){ke("acceptedLanguage");return}if(!e?.shop?.currency){ke("currency");return}if(!e?.shop?.hydrogenSubchannelId){ke("hydrogenSubchannelId");return}return {shopifySalesChannel:"hydrogen",assetVersionId:ur,...e.shop,hasUserConsent:r,...getClientBrowserParameters(),ccpaEnforced:!t.saleOfDataAllowed(),gdprEnforced:!(t.marketingAllowed()&&t.analyticsProcessingAllowed()),analyticsAllowed:t.analyticsProcessingAllowed(),marketingAllowed:t.marketingAllowed(),saleOfDataAllowed:t.saleOfDataAllowed()}}function Lo(e,t){if(t===null)return;let r=Ae(e);return r?{...r,cartId:t.id}:void 0}var Z={};function ko(e){let t=Ae(e);t&&(sendShopifyAnalytics({eventName:AnalyticsEventName.PAGE_VIEW_2,payload:{...t,...Z}}),Z={});}function No(e){let t=Ae(e);if(t&&yr({type:"product",products:e.products})){let r=nt(e.products);Z={pageType:AnalyticsPageType.product,resourceId:r[0].productGid},t={...t,...Z,products:nt(e.products)},sendShopifyAnalytics({eventName:AnalyticsEventName.PRODUCT_VIEW,payload:t});}}function Vo(e){let t=Ae(e);t&&(Z={pageType:AnalyticsPageType.collection,resourceId:e.collection.id},t={...t,...Z,collectionHandle:e.collection.handle,collectionId:e.collection.id},sendShopifyAnalytics({eventName:AnalyticsEventName.COLLECTION_VIEW,payload:t}));}function Mo(e){let t=Ae(e);t&&(Z={pageType:AnalyticsPageType.search},t={...t,...Z,searchString:e.searchTerm},sendShopifyAnalytics({eventName:AnalyticsEventName.SEARCH_VIEW,payload:t}));}function qo(e){let{cart:t,currentLine:r}=e,n=Lo(e,t);!n||!r?.id||$o({matchedLine:r,eventPayload:n});}function $o({matchedLine:e,eventPayload:t}){let r={id:e.merchandise.product.id,variantId:e.merchandise.id,title:e.merchandise.product.title,variantTitle:e.merchandise.title,vendor:e.merchandise.product.vendor,price:e.merchandise.price.amount,quantity:e.quantity,productType:e.merchandise.product.productType,sku:e.merchandise.sku};yr({type:"cart",products:[r]})&&sendShopifyAnalytics({eventName:AnalyticsEventName.ADD_TO_CART,payload:{...t,products:nt([r])}});}function ae(e,t,r,n){if(e==="cart"){let o=`${r?"merchandise":"merchandise.product"}.${t}`;console.error(`[h2:error:ShopifyAnalytics] Can't set up cart analytics events because the \`cart.lines[].${o}\` value is missing from your GraphQL cart query. In your project, search for where \`fragment CartLine on CartLine\` is defined and make sure \`${o}\` is part of your cart query. Check the Hydrogen Skeleton template for reference: https://github.com/Shopify/hydrogen/blob/main/templates/skeleton/app/lib/fragments.ts#L25-L56.`);}else {let o=`${n||t}`;console.error(`[h2:error:ShopifyAnalytics] Can't set up product view analytics events because the \`${o}\` is missing from your \`<Analytics.ProductView>\`. Make sure \`${o}\` is part of your products data prop. Check the Hydrogen Skeleton template for reference: https://github.com/Shopify/hydrogen/blob/main/templates/skeleton/app/routes/products.%24handle.tsx#L159-L165.`);}}function yr({type:e,products:t}){return !t||t.length===0?(ae(e,"",false,"data.products"),false):(t.forEach(r=>{if(!r.id)return ae(e,"id",false),false;if(!r.title)return ae(e,"title",false),false;if(!r.price)return ae(e,"price.amount",true,"price"),false;if(!r.vendor)return ae(e,"vendor",false),false;if(!r.variantId)return ae(e,"id",true,"variantId"),false;if(!r.variantTitle)return ae(e,"title",true,"variantTitle"),false}),true)}function nt(e){return e.map(t=>{let r={productGid:t.id,variantGid:t.variantId,name:t.title,variantName:t.variantTitle,brand:t.vendor,price:t.price,quantity:t.quantity||1,category:t.productType};return t.sku&&(r.sku=t.sku),t.productType&&(r.category=t.productType),r})}function gr(e){console.error(`[h2:error:CartAnalytics] Can't set up cart analytics events because the \`cart.${e}\` value is missing from your GraphQL cart query. In your project, search for where \`fragment CartApiQuery on Cart\` is defined and make sure \`${e}\` is part of your cart query. Check the Hydrogen Skeleton template for reference: https://github.com/Shopify/hydrogen/blob/main/templates/skeleton/app/lib/fragments.ts#L59.`);}function hr({cart:e,setCarts:t}){let{publish:r,shop:n,customData:o,canTrack:a,cart:i,prevCart:c}=B(),s=useRef(null);return useEffect(()=>{if(e)return Promise.resolve(e).then(u=>{if(u&&u.lines){if(!u.id){gr("id");return}if(!u.updatedAt){gr("updatedAt");return}}t(({cart:p,prevCart:l})=>u?.updatedAt!==p?.updatedAt?{cart:u,prevCart:p}:{cart:p,prevCart:l});}),()=>{}},[t,e]),useEffect(()=>{if(!i||!i?.updatedAt||i?.updatedAt===c?.updatedAt)return;let u;try{u=JSON.parse(localStorage.getItem("cartLastUpdatedAt")||"");}catch{u=null;}if(i.id===u?.id&&i.updatedAt===u?.updatedAt)return;let p={eventTimestamp:Date.now(),cart:i,prevCart:c,shop:n,customData:o};if(i.updatedAt===s.current)return;s.current=i.updatedAt,r("cart_updated",p),localStorage.setItem("cartLastUpdatedAt",JSON.stringify({id:i.id,updatedAt:i.updatedAt}));let l=c?.lines?flattenConnection(c?.lines):[],m=i.lines?flattenConnection(i.lines):[];l?.forEach(y=>{let d=m.filter(g=>y.id===g.id);if(d?.length===1){let g=d[0];y.quantity<g.quantity?r("product_added_to_cart",{...p,prevLine:y,currentLine:g}):y.quantity>g.quantity&&r("product_removed_from_cart",{...p,prevLine:y,currentLine:g});}else r("product_removed_from_cart",{...p,prevLine:y});}),m?.forEach(y=>{let d=l.filter(g=>y.id===g.id);(!d||d.length===0)&&r("product_added_to_cart",{...p,currentLine:y});});},[i,c,r,n,o,a]),null}var Wo="https://cdn.shopify.com/shopifycloud/perf-kit/shopify-perf-kit-1.0.1.min.js";function Cr({shop:e}){let t=useRef(false),{subscribe:r,register:n}=B(),{ready:o}=n("Internal_Shopify_Perf_Kit"),a=useLoadScript(Wo,{attributes:{id:"perfkit","data-application":"hydrogen","data-shop-id":parseGid(e.shopId).id.toString(),"data-storefront-id":e.hydrogenSubchannelId,"data-monorail-region":"global","data-spa-mode":"true","data-resource-timing-sampling-rate":"100"}});return useEffect(()=>{a!=="done"||t.current||(t.current=true,r(V.PAGE_VIEWED,()=>{window.PerfKit?.navigate();}),r(V.PRODUCT_VIEWED,()=>{window.PerfKit?.setPageType("product");}),r(V.COLLECTION_VIEWED,()=>{window.PerfKit?.setPageType("collection");}),r(V.SEARCH_VIEWED,()=>{window.PerfKit?.setPageType("search");}),r(V.CART_VIEWED,()=>{window.PerfKit?.setPageType("cart");}),o());},[r,o,a]),null}var Pr=new Set,G=e=>{Pr.has(e)||(console.warn(e),Pr.add(e));},Ar=new Set,it=e=>{Ar.has(e)||(console.error(new Error(e)),Ar.add(e));};var Xo={canTrack:()=>false,cart:null,customData:{},prevCart:null,publish:()=>{},shop:null,subscribe:()=>{},register:()=>({ready:()=>{}}),customerPrivacy:null,privacyBanner:null},Er=createContext(Xo),Me=new Map,Se={};function wr(){return Object.values(Se).every(Boolean)}function Sr(e,t){Me.has(e)||Me.set(e,new Map),Me.get(e)?.set(t.toString(),t);}var qe=new Map;function Tr(e,t){if(!wr()){qe.set(e,t);return}br(e,t);}function br(e,t){(Me.get(e)??new Map).forEach((r,n)=>{try{r(t);}catch(o){typeof o=="object"&&o instanceof Error?console.error("Analytics publish error",o.message,n,o.stack):console.error("Analytics publish error",o,n);}});}function vr(e){return Se.hasOwnProperty(e)||(Se[e]=false),{ready:()=>{Se[e]=true,wr()&&qe.size>0&&(qe.forEach((t,r)=>{br(r,t);}),qe.clear());}}}function Ir(){try{return window.Shopify.customerPrivacy.analyticsProcessingAllowed()}catch{}return false}function Rr(e,t){return `[h2:error:Analytics.Provider] - ${e} is required. Make sure ${t} is defined in your environment variables. See https://h2o.fyi/analytics/consent to learn how to setup environment variables in the Shopify admin.`}function Zo({canTrack:e,cart:t,children:r,consent:n,customData:o={},shop:a=null,cookieDomain:i}){let c=useRef(false),{shop:s}=en(a),[u,p]=useState(!!e),[l,m]=useState({cart:null,prevCart:null}),[y,d]=useState(e?()=>e:()=>Ir);if(s)if(/\/68817551382$/.test(s.shopId))G("[h2:error:Analytics.Provider] - Mock shop is used. Analytics will not work properly.");else {if(!n.checkoutDomain){let P=Rr("consent.checkoutDomain","PUBLIC_CHECKOUT_DOMAIN");it(P);}if(!n.storefrontAccessToken){let P=Rr("consent.storefrontAccessToken","PUBLIC_STOREFRONT_API_TOKEN");it(P);}n?.country||(n.country="US"),n?.language||(n.language="EN"),n.withPrivacyBanner===void 0&&(n.withPrivacyBanner=false);}let g=useMemo(()=>({canTrack:y,...l,customData:o,publish:y()?Tr:()=>{},shop:s,subscribe:Sr,register:vr,customerPrivacy:de(),privacyBanner:Le()}),[u,y,l,l.cart?.updatedAt,l.prevCart,Tr,Sr,o,s,vr,JSON.stringify(Se),de,Le]);return jsxs(Er.Provider,{value:g,children:[r,!!s&&jsx(Xt,{}),!!s&&!!t&&jsx(hr,{cart:t,setCarts:m}),!!s&&n.checkoutDomain&&jsx(lr,{consent:n,onReady:()=>{c.current=true,p(true),d(e?()=>e:()=>Ir);},domain:i}),!!s&&jsx(Cr,{shop:s})]})}function B(){let e=useContext(Er);if(!e)throw new Error("[h2:error:useAnalytics] 'useAnalytics()' must be a descendent of <AnalyticsProvider/>");return e}function en(e){let[t,r]=useState(null);return useEffect(()=>(Promise.resolve(e).then(r),()=>{}),[r,e]),{shop:t}}async function tn({storefront:e,publicStorefrontId:t="0"}){return e.query(rn,{cache:e.CacheLong()}).then(({shop:r,localization:n})=>({shopId:r.id,acceptedLanguage:n.language.isoCode,currency:n.country.currency.isoCode,hydrogenSubchannelId:t}))}var rn=`#graphql
query ShopData(
$country: CountryCode
$language: LanguageCode
) @inContext(country: $country, language: $language) {
shop {
id
}
localization {
country {
currency {
isoCode
}
}
language {
isoCode
}
}
}
`,on={CartView:tr,CollectionView:er,CustomView:or,ProductView:Zt,Provider:Zo,SearchView:rr};function Q(e,t){return st(e.headers,t)}function st(e,t){let r=e?.get?.(t)??e?.[t];return typeof r=="string"?r:null}function ee(e){return {requestId:e?Q(e,"request-id"):void 0,purpose:e?Q(e,"purpose"):void 0}}function le(e,t={}){let r=new Error,n=(o,a="Error")=>{let i=(r.stack??"").split(`
`).slice(3+(t.stackOffset??0)).join(`
`).replace(/ at loader(\d+) \(/,(c,s)=>c.replace(s,""));return `${a}: ${o}
`+i};return e.then(o=>{if(o?.errors&&Array.isArray(o.errors)){let a=typeof t.logErrors=="function"?t.logErrors:()=>t.logErrors??false;o.errors.forEach(i=>{i&&(i.stack=n(i.message,i.name),a(i)&&console.error(i));});}return o}).catch(o=>{throw o&&(o.stack=n(o.message,o.name)),o})}var $=void 0;var $e="public",an="private",ct="no-store",Or={maxAge:"max-age",staleWhileRevalidate:"stale-while-revalidate",sMaxAge:"s-maxage",staleIfError:"stale-if-error"};function Te(e){let t=[];return Object.keys(e).forEach(r=>{r==="mode"?t.push(e[r]):Or[r]&&t.push(`${Or[r]}=${e[r]}`);}),t.join(", ")}function ut(){return {mode:ct}}function pt(e){if(e?.mode&&e?.mode!==$e&&e?.mode!==an)throw Error("'mode' must be either 'public' or 'private'")}function ie(e){return pt(e),{mode:$e,maxAge:1,staleWhileRevalidate:9,...e}}function dt(e){return pt(e),{mode:$e,maxAge:3600,staleWhileRevalidate:82800,...e}}function ye(e){return pt(e),{mode:$e,maxAge:1,staleWhileRevalidate:86399,...e}}function lt(e){return e}function W(e){return String(e).includes("__proto__")?JSON.parse(e,sn):JSON.parse(e)}function sn(e,t){if(e!=="__proto__")return t}function Fe(e,t){return e&&t?{...e,...t}:e||ye()}function yt(e){return Te(Fe(e))}async function cn(e,t){if(!e)return;let r=await e.match(t);if(!r){return}return r}async function un(e,t,r,n){if(!e)return;let o=Fe(n),a=yt(Fe(o,{maxAge:(o.maxAge||0)+(o.staleWhileRevalidate||0)})),i=yt(Fe(o));r.headers.set("cache-control",a),r.headers.set("real-cache-control",i),r.headers.set("cache-put-date",String(Date.now())),await e.put(t,r);}async function pn(e,t){e&&await e.delete(t);}function dn(e,t){let r=e.headers.get("real-cache-control"),n=0;if(r){let a=r.match(/max-age=(\d*)/);a&&a.length>1&&(n=parseFloat(a[1]));}return [(Date.now()-Number(t))/1e3,n]}function ln(e,t){let r=t.headers.get("cache-put-date");if(!r)return false;let[n,o]=dn(t,r),a=n>o;return a}var He={get:cn,set:un,delete:pn,generateDefaultCacheControlHeader:yt,isStale:ln};function ve(e){return `https://shopify.dev/?${e}`}function yn(e){return e||ye()}async function xr(e,t){if(!e)return;let r=ve(t),n=new Request(r),o=await He.get(e,n);if(!o)return;let a=await o.text();try{return [W(a),o]}catch{return [a,o]}}async function Dr(e,t,r,n){if(!e)return;let o=ve(t),a=new Request(o),i=new Response(JSON.stringify(r));await He.set(e,a,i,yn(n));}function _r(e,t){return He.isStale(new Request(ve(e)),t)}function Ur(e){let t=Array.isArray(e)?e:[e],r="";for(let n of t)n!=null&&(typeof n=="object"?r+=JSON.stringify(n):r+=n.toString());return encodeURIComponent(r)}var ft=new Set;async function Be(e,t,{strategy:r=ie(),cacheInstance:n,shouldCacheResult:o=()=>true,waitUntil:a,debugInfo:i}){let s=Ur([...typeof e=="string"?[e]:e]),l=f=>{({displayName:f.displayName,url:f.response?.url,responseInit:{status:f.response?.status||0,statusText:f.response?.statusText||"",headers:Array.from(f.response?.headers.entries()||[])}});},y=void 0;if(!n||!r||r.mode===ct){let f=await t({addDebugData:l});return f}let d=f=>Dr(n,s,{value:f,debugInfo:void 0},r),g=await xr(n,s);if(g&&typeof g[0]!="string"){let[{value:f,debugInfo:h},S]=g;let w=_r(s,S)?"STALE":"HIT";if(!ft.has(s)&&w==="STALE"){ft.add(s);let D=Promise.resolve().then(async()=>{let L=Date.now();try{let O=await t({addDebugData:l});o(O)&&(await d(O),y?.({result:O,cacheStatus:"PUT",overrideStartTime:L}));}catch(O){O.message&&(O.message="SWR in sub-request failed: "+O.message),console.error(O);}finally{ft.delete(s);}});a?.(D);}return f}let P=await t({addDebugData:l});if(o(P)){let f=Promise.resolve().then(async()=>{await d(P);});a?.(f);}return P}function fn(e,t){return [e,{status:t.status,statusText:t.statusText,headers:Array.from(t.headers.entries())}]}function Lr([e,t]){return [e,new Response(e,t)]}async function Ge(e,t,{cacheInstance:r,cache:n,cacheKey:o=[e,t],shouldCacheResponse:a,waitUntil:i,debugInfo:c}){return !n&&(!t.method||t.method==="GET")&&(n=ie()),Be(o,async()=>{let s=await fetch(e,t);if(!s.ok)return s;let u=await s.text().catch(()=>"");try{u&&(u=W(u));}catch{}return fn(u,s)},{cacheInstance:r,waitUntil:i,strategy:n??null,debugInfo:c,shouldCacheResult:s=>"ok"in s?!1:a(...Lr(s))}).then(s=>"ok"in s?[null,s]:Lr(s))}function mn(e){let{cache:t,waitUntil:r,request:n}=e;return {run:({cacheKey:o,cacheStrategy:a,shouldCacheResult:i},c)=>Be(o,c,{shouldCacheResult:i,strategy:a,cacheInstance:t,waitUntil:r,debugInfo:{...ee(n),stackInfo:$?.()}}),fetch:(o,a,i)=>Ge(o,a??{},{waitUntil:r,cacheKey:[o,a],cacheInstance:t,debugInfo:{url:o,...ee(n),stackInfo:$?.(),displayName:i?.displayName},cache:i.cacheStrategy,...i}).then(([c,s])=>({data:c,response:s}))}}var mt=class{#e;constructor(){this.#e=new Map;}add(t){throw new Error("Method not implemented. Use `put` instead.")}addAll(t){throw new Error("Method not implemented. Use `put` instead.")}matchAll(t,r){throw new Error("Method not implemented. Use `match` instead.")}async put(t,r){if(t.method!=="GET")throw new TypeError("Cannot cache response to non-GET request.");if(r.status===206)throw new TypeError("Cannot cache response to a range request (206 Partial Content).");if(r.headers.get("vary")?.includes("*"))throw new TypeError("Cannot cache response with 'Vary: *' header.");this.#e.set(t.url,{body:new Uint8Array(await r.arrayBuffer()),status:r.status,headers:[...r.headers],timestamp:Date.now()});}async match(t){if(t.method!=="GET")return;let r=this.#e.get(t.url);if(!r)return;let{body:n,timestamp:o,...a}=r,i=new Headers(a.headers),c=i.get("cache-control")||i.get("real-cache-control")||"",s=parseInt(c.match(/max-age=(\d+)/)?.[1]||"0",10),u=parseInt(c.match(/stale-while-revalidate=(\d+)/)?.[1]||"0",10),p=(Date.now()-o)/1e3;if(p>s+u){this.#e.delete(t.url);return}let m=p>s;return i.set("cache",m?"STALE":"HIT"),i.set("date",new Date(o).toUTCString()),new Response(n,{status:a.status??200,headers:i})}async delete(t){return this.#e.has(t.url)?(this.#e.delete(t.url),true):false}keys(t){let r=[];for(let n of this.#e.keys())(!t||t.url===n)&&r.push(new Request(n));return Promise.resolve(r)}};var kr="cartFormInput";function j({children:e,action:t,inputs:r,route:n,fetcherKey:o}){let a=useFetcher({key:o});return jsxs(a.Form,{action:n||"",method:"post",children:[(t||r)&&jsx("input",{type:"hidden",name:kr,value:JSON.stringify({action:t,inputs:r})}),typeof e=="function"?e(a):e]})}j.INPUT_NAME=kr;j.ACTIONS={AttributesUpdateInput:"AttributesUpdateInput",BuyerIdentityUpdate:"BuyerIdentityUpdate",Create:"Create",DiscountCodesUpdate:"DiscountCodesUpdate",GiftCardCodesUpdate:"GiftCardCodesUpdate",LinesAdd:"LinesAdd",LinesRemove:"LinesRemove",LinesUpdate:"LinesUpdate",NoteUpdate:"NoteUpdate",SelectedDeliveryOptionsUpdate:"SelectedDeliveryOptionsUpdate",MetafieldsSet:"MetafieldsSet",MetafieldDelete:"MetafieldDelete"};function hn(e){let t={};for(let i of e.entries()){let c=i[0],s=e.getAll(c);t[c]=s.length>1?s:i[1];}let{cartFormInput:r,...n}=t,{action:o,inputs:a}=r?JSON.parse(String(r)):{};return {action:o,inputs:{...a,...n}}}j.getFormInput=hn;var gt=e=>{let t=parse(st(e,"Cookie")||"");return ()=>t.cart?`gid://shopify/Cart/${t.cart}`:void 0};var ht=e=>t=>{let r=new Headers;return r.append("Set-Cookie",stringify("cart",t.split("/").pop()||"",{path:"/",...e})),r};var Ct="Custom-Storefront-Request-Group-ID",Pt="X-Shopify-Storefront-Access-Token",At="X-SDK-Variant",St="X-SDK-Variant-Source",Tt="X-SDK-Version";function Nr(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():`weak-${Math.random().toString(16).substring(2)}`}var Ie="2025.1.3";function fe(e){return e.replace(/\s*#.*$/gm,"").replace(/\s+/gm," ").trim()}var Tn=/(^|}\s)query[\s({]/im,vn=/(^|}\s)mutation[\s({]/im;function Qe(e,t){if(!Tn.test(e))throw new Error(`[h2:error:${t}] Can only execute queries`)}function We(e,t){if(!vn.test(e))throw new Error(`[h2:error:${t}] Can only execute mutations`)}var se=class extends Error{locations;path;extensions;constructor(t,r={}){let o=(r.clientOperation?`[h2:error:${r.clientOperation}] `:"")+t+(r.requestId?` - Request ID: ${r.requestId}`:"");super(o),this.name="GraphQLError",this.extensions=r.extensions,this.locations=r.locations,this.path=r.path,this.stack=r.stack||void 0;try{this.cause=JSON.stringify({...typeof r.cause=="object"?r.cause:{},requestId:r.requestId});}catch{r.cause&&(this.cause=r.cause);}}get[Symbol.toStringTag](){return this.name}toString(){let t=`${this.name}: ${this.message}`;if(this.path)try{t+=` | path: ${JSON.stringify(this.path)}`;}catch{}if(this.extensions)try{t+=` | extensions: ${JSON.stringify(this.extensions)}`;}catch{}return t+=`
`,this.stack&&(t+=`${this.stack.slice(this.stack.indexOf(`
`)+1)}
`),t}toJSON(){return {name:"Error",message:""}}};function Re({url:e,response:t,errors:r,type:n,query:o,queryVariables:a,ErrorConstructor:i=Error,client:c="storefront"}){let s=(typeof r=="string"?r:r?.map?.(p=>p.message).join(`
`))||`URL: ${e}
API response error: ${t.status}`,u=new se(s,{query:o,queryVariables:a,cause:{errors:r},clientOperation:`${c}.${n}`,requestId:t.headers.get("x-request-id")});throw new i(u.message,{cause:u.cause})}var On={language:"EN",country:"US"};function $r(e){let {storefrontHeaders:t,cache:r,waitUntil:n,i18n:o,storefrontId:a,logErrors:i=true,...c}=e,{getPublicTokenHeaders:u,getPrivateTokenHeaders:p,getStorefrontApiUrl:l,getShopifyDomain:m}=createStorefrontClient(c),d=(c.privateStorefrontToken?p:u)({contentType:"json",buyerIp:t?.buyerIp||""});if(d[Ct]=t?.requestGroupId||Nr(),a&&(d[SHOPIFY_STOREFRONT_ID_HEADER]=a),(d["user-agent"]=`Hydrogen ${Ie}`),t&&t.cookie){let f=getShopifyCookies(t.cookie??"");f[SHOPIFY_Y]&&(d[SHOPIFY_STOREFRONT_Y_HEADER]=f[SHOPIFY_Y]),f[SHOPIFY_S]&&(d[SHOPIFY_STOREFRONT_S_HEADER]=f[SHOPIFY_S]);}let g=JSON.stringify({"content-type":d["content-type"],"user-agent":d["user-agent"],[At]:d[At],[St]:d[St],[Tt]:d[Tt],[Pt]:d[Pt]});async function P({query:f,mutation:h,variables:S,cache:w,headers:D=[],storefrontApiVersion:L,displayName:O,stackInfo:F}){let xe=D instanceof Headers?Object.fromEntries(D.entries()):Array.isArray(D)?Object.fromEntries(D):D,oe=f??h,Y={...S};o&&(!S?.country&&/\$country/.test(oe)&&(Y.country=o.country),!S?.language&&/\$language/.test(oe)&&(Y.language=o.language));let ne=l({storefrontApiVersion:L}),C=JSON.stringify({query:oe,variables:Y}),A={method:"POST",headers:{...d,...xe},body:C},x=[ne,A.method,g,A.body],[b,q]=await Ge(ne,A,{cacheInstance:h?void 0:r,cache:w||ye(),cacheKey:x,waitUntil:n,shouldCacheResponse:v=>!v?.errors,debugInfo:{requestId:A.headers[Ct],displayName:O,url:ne,stackInfo:F,graphql:C,purpose:t?.purpose}}),H={url:ne,response:q,type:h?"mutation":"query",query:oe,queryVariables:Y,errors:void 0};if(!q.ok){let v,N=b;try{N??=await q.text(),v=W(N);}catch{v=[{message:N??"Could not parse Storefront API response"}];}Re({...H,errors:v});}let{data:k,errors:J}=b,X=J?.map(({message:v,...N})=>new se(v,{...N,clientOperation:`storefront.${H.type}`,requestId:q.headers.get("x-request-id"),queryVariables:Y,query:oe}));return T(k,X)}return {storefront:{query(f,h){f=fe(f),Qe(f,"storefront.query");let S=qr?.(f);return le(P({...h,query:f,stackInfo:$?.(S)}),{stackOffset:S,logErrors:i})},mutate(f,h){f=fe(f),We(f,"storefront.mutate");let S=qr?.(f);return le(P({...h,mutation:f,stackInfo:$?.(S)}),{stackOffset:S,logErrors:i})},cache:r,CacheNone:ut,CacheLong:dt,CacheShort:ie,CacheCustom:lt,generateCacheControlHeader:Te,getPublicTokenHeaders:u,getPrivateTokenHeaders:p,getShopifyDomain:m,getApiUrl:l,i18n:o??On}}}var qr=void 0;function T(e,t){return {...e,...t&&{errors:t}}}function vt({storefront:e,customerAccount:t,getCartId:r,cartFragment:n}){return async o=>{let a=r();if(!a)return null;let[i,{cart:c,errors:s}]=await Promise.all([t?t.isLoggedIn():false,e.query(xn(n),{variables:{cartId:a,...o},cache:e.CacheNone()})]);if(i&&c?.checkoutUrl){let u=new URL(c.checkoutUrl);u.searchParams.set("logged_in","true"),c.checkoutUrl=u.toString();}return c||s?T(c,s):null}}var xn=(e=Dn)=>`#graphql
query CartQuery(
$cartId: ID!
$numCartLines: Int = 100
$country: CountryCode = ZZ
$language: LanguageCode
) @inContext(country: $country, language: $language) {
cart(id: $cartId) {
...CartApiQuery
}
}
${e}
`,Dn=`#graphql
fragment CartApiQuery on Cart {
updatedAt
id
checkoutUrl
totalQuantity
buyerIdentity {
countryCode
customer {
id
email
firstName
lastName
displayName
}
email
phone
}
lines(first: $numCartLines) {
edges {
node {
id
quantity
attributes {
key
value
}
cost {
totalAmount {
amount
currencyCode
}
amountPerQuantity {
amount
currencyCode
}
compareAtAmountPerQuantity {
amount
currencyCode
}
}
merchandise {
... on ProductVariant {
id
availableForSale
compareAtPrice {
...CartApiMoney
}
price {
...CartApiMoney
}
requiresShipping
title
image {
...CartApiImage
}
product {
handle
title
id
vendor
}
selectedOptions {
name
value
}
}
}
}
}
}
cost {
subtotalAmount {
...CartApiMoney
}
totalAmount {
...CartApiMoney
}
totalDutyAmount {
...CartApiMoney
}
totalTaxAmount {
...CartApiMoney
}
}
note
attributes {
key
value
}
discountCodes {
applicable
code
}
}
fragment CartApiMoney on MoneyV2 {
currencyCode
amount
}
fragment CartApiImage on Image {
id
url
altText
width
height
}
`;var I=`#graphql
fragment CartApiError on CartUserError {
message
field
code
}
`,R=`#graphql
fragment CartApiMutation on Cart {
id
totalQuantity
checkoutUrl
}
`,E=`#graphql
fragment CartApiWarning on CartWarning {
code
message
target
}
`;function It(e){return async(t,r)=>{let n=e.customerAccount?await e.customerAccount.getBuyer():void 0,{cartId:o,...a}=r||{},{buyerIdentity:i,...c}=t,{cartCreate:s,errors:u}=await e.storefront.mutate(_n(e.cartFragment),{variables:{input:{...c,buyerIdentity:{...n,...i}},...a}});return T(s,u)}}var _n=(e=R)=>`#graphql
mutation cartCreate(
$input: CartInput!
$country: CountryCode = ZZ
$language: LanguageCode
) @inContext(country: $country, language: $language) {
cartCreate(input: $input) {
cart {
...CartApiMutation
checkoutUrl
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function Rt(e){return async(t,r)=>{let{cartLinesAdd:n,errors:o}=await e.storefront.mutate(Un(e.cartFragment),{variables:{cartId:e.getCartId(),lines:t,...r}});return T(n,o)}}var Un=(e=R)=>`#graphql
mutation cartLinesAdd(
$cartId: ID!
$lines: [CartLineInput!]!
$country: CountryCode = ZZ
$language: LanguageCode
) @inContext(country: $country, language: $language) {
cartLinesAdd(cartId: $cartId, lines: $lines) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;var Fr="__h_pending_";function Hr(e){return Fr+e}function je(e){return e.startsWith(Fr)}function Ke(e,t){if(t.some(r=>je(typeof r=="string"?r:r.id)))throw new Error(`Tried to perform an action on an optimistic line. Make sure to disable your "${e}" CartForm action when the line is optimistic.`)}function Et(e){return async(t,r)=>{Ke("updateLines",t);let{cartLinesUpdate:n,errors:o}=await e.storefront.mutate(Ln(e.cartFragment),{variables:{cartId:e.getCartId(),lines:t,...r}});return T(n,o)}}var Ln=(e=R)=>`#graphql
mutation cartLinesUpdate(
$cartId: ID!
$lines: [CartLineUpdateInput!]!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartLinesUpdate(cartId: $cartId, lines: $lines) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function wt(e){return async(t,r)=>{Ke("removeLines",t);let{cartLinesRemove:n,errors:o}=await e.storefront.mutate(kn(e.cartFragment),{variables:{cartId:e.getCartId(),lineIds:t,...r}});return T(n,o)}}var kn=(e=R)=>`#graphql
mutation cartLinesRemove(
$cartId: ID!
$lineIds: [ID!]!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartLinesRemove(cartId: $cartId, lineIds: $lineIds) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function bt(e){return async(t,r)=>{let n=t.filter((i,c,s)=>s.indexOf(i)===c),{cartDiscountCodesUpdate:o,errors:a}=await e.storefront.mutate(Nn(e.cartFragment),{variables:{cartId:e.getCartId(),discountCodes:n,...r}});return T(o,a)}}var Nn=(e=R)=>`#graphql
mutation cartDiscountCodesUpdate(
$cartId: ID!
$discountCodes: [String!]
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartDiscountCodesUpdate(cartId: $cartId, discountCodes: $discountCodes) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function Ot(e){return async(t,r)=>{t.companyLocationId&&e.customerAccount&&e.customerAccount.setBuyer({companyLocationId:t.companyLocationId});let n=e.customerAccount?await e.customerAccount.getBuyer():void 0,{cartBuyerIdentityUpdate:o,errors:a}=await e.storefront.mutate(Vn(e.cartFragment),{variables:{cartId:e.getCartId(),buyerIdentity:{...n,...t},...r}});return T(o,a)}}var Vn=(e=R)=>`#graphql
mutation cartBuyerIdentityUpdate(
$cartId: ID!
$buyerIdentity: CartBuyerIdentityInput!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartBuyerIdentityUpdate(cartId: $cartId, buyerIdentity: $buyerIdentity) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function xt(e){return async(t,r)=>{let{cartNoteUpdate:n,errors:o}=await e.storefront.mutate(Mn(e.cartFragment),{variables:{cartId:e.getCartId(),note:t,...r}});return T(n,o)}}var Mn=(e=R)=>`#graphql
mutation cartNoteUpdate(
$cartId: ID!
$note: String!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartNoteUpdate(cartId: $cartId, note: $note) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function Dt(e){return async(t,r)=>{let{cartSelectedDeliveryOptionsUpdate:n,errors:o}=await e.storefront.mutate(qn(e.cartFragment),{variables:{cartId:e.getCartId(),selectedDeliveryOptions:t,...r}});return T(n,o)}}var qn=(e=R)=>`#graphql
mutation cartSelectedDeliveryOptionsUpdate(
$cartId: ID!
$selectedDeliveryOptions: [CartSelectedDeliveryOptionInput!]!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartSelectedDeliveryOptionsUpdate(cartId: $cartId, selectedDeliveryOptions: $selectedDeliveryOptions) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function _t(e){return async(t,r)=>{let{cartAttributesUpdate:n,errors:o}=await e.storefront.mutate($n(e.cartFragment),{variables:{cartId:r?.cartId||e.getCartId(),attributes:t}});return T(n,o)}}var $n=(e=R)=>`#graphql
mutation cartAttributesUpdate(
$cartId: ID!
$attributes: [AttributeInput!]!
) {
cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function Ut(e){return async(t,r)=>{let n=r?.cartId||e.getCartId(),o=t.map(c=>({...c,ownerId:n})),{cartMetafieldsSet:a,errors:i}=await e.storefront.mutate(Fn(),{variables:{metafields:o}});return T({cart:{id:n},...a},i)}}var Fn=()=>`#graphql
mutation cartMetafieldsSet(
$metafields: [CartMetafieldsSetInput!]!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartMetafieldsSet(metafields: $metafields) {
userErrors {
code
elementIndex
field
message
}
}
}
`;function Lt(e){return async(t,r)=>{let n=r?.cartId||e.getCartId(),{cartMetafieldDelete:o,errors:a}=await e.storefront.mutate(Hn(),{variables:{input:{ownerId:n,key:t}}});return T({cart:{id:n},...o},a)}}var Hn=()=>`#graphql
mutation cartMetafieldDelete(
$input: CartMetafieldDeleteInput!
) {
cartMetafieldDelete(input: $input) {
userErrors {
code
field
message
}
}
}
`;function kt(e){return async(t,r)=>{let n=t.filter((i,c,s)=>s.indexOf(i)===c),{cartGiftCardCodesUpdate:o,errors:a}=await e.storefront.mutate(Bn(e.cartFragment),{variables:{cartId:e.getCartId(),giftCardCodes:n,...r}});return T(o,a)}}var Bn=(e=R)=>`#graphql
mutation cartGiftCardCodesUpdate(
$cartId: ID!
$giftCardCodes: [String!]!
$language: LanguageCode
$country: CountryCode
) @inContext(country: $country, language: $language) {
cartGiftCardCodesUpdate(cartId: $cartId, giftCardCodes: $giftCardCodes) {
cart {
...CartApiMutation
}
userErrors {
...CartApiError
}
warnings {
...CartApiWarning
}
}
}
${e}
${I}
${E}
`;function Nt(e){let{getCartId:t,setCartId:r,storefront:n,customerAccount:o,cartQueryFragment:a,cartMutateFragment:i}=e,c=t(),s=()=>c||t(),u={storefront:n,getCartId:s,cartFragment:i,customerAccount:o},p=It(u),l=async function(...y){let d=await p(...y);return c=d?.cart?.id,d},m={get:vt({storefront:n,customerAccount:o,getCartId:s,cartFragment:a}),getCartId:s,setCartId:r,create:l,addLines:async(y,d)=>{let g=y.map(P=>({attributes:P.attributes,quantity:P.quantity,merchandiseId:P.merchandiseId,sellingPlanId:P.sellingPlanId}));return c||d?.cartId?await Rt(u)(g,d):await l({lines:g},d)},updateLines:Et(u),removeLines:wt(u),updateDiscountCodes:async(y,d)=>c||d?.cartId?await bt(u)(y,d):await l({discountCodes:y},d),updateGiftCardCodes:async(y,d)=>c||d?.cartId?await kt(u)(y,d):await l({giftCardCodes:y},d),updateBuyerIdentity:async(y,d)=>c||d?.cartId?await Ot(u)(y,d):await l({buyerIdentity:y},d),updateNote:async(y,d)=>c||d?.cartId?await xt(u)(y,d):await l({note:y},d),updateSelectedDeliveryOption:Dt(u),updateAttributes:async(y,d)=>c||d?.cartId?await _t(u)(y,d):await l({attributes:y},d),setMetafields:async(y,d)=>c||d?.cartId?await Ut(u)(y,d):await l({metafields:y},d),deleteMetafield:Lt(u)};return "customMethods"in e?{...m,...e.customMethods??{}}:m}function Qn(e){let t=useFetchers();if(!t||!t.length)return e;let r=e?.lines?structuredClone(e):{lines:{nodes:[]}},n=r.lines.nodes,o=false;for(let{formData:a}of t){if(!a)continue;let i=j.getFormInput(a);if(i.action===j.ACTIONS.LinesAdd)for(let c of i.inputs.lines){if(!c.selectedVariant){console.error("[h2:error:useOptimisticCart] No selected variant was passed in the cart action. Make sure to pass the selected variant if you want to use an optimistic cart");continue}let s=n.find(u=>u.merchandise.id===c.selectedVariant?.id);o=true,s?(s.quantity=(s.quantity||1)+(c.quantity||1),s.isOptimistic=true):n.unshift({id:Hr(c.selectedVariant.id),merchandise:c.selectedVariant,isOptimistic:true,quantity:c.quantity||1});}else if(i.action===j.ACTIONS.LinesRemove)for(let c of i.inputs.lineIds){let s=n.findIndex(u=>u.id===c);if(s!==-1){if(je(n[s].id)){console.error("[h2:error:useOptimisticCart] Tried to remove an optimistic line that has not been added to the cart yet");continue}n.splice(s,1),o=true;}else console.warn(`[h2:warn:useOptimisticCart] Tried to remove line '${c}' but it doesn't exist in the cart`);}else if(i.action===j.ACTIONS.LinesUpdate)for(let c of i.inputs.lines){let s=n.findIndex(u=>c.id===u.id);if(s>-1){if(je(n[s].id)){console.error("[h2:error:useOptimisticCart] Tried to update an optimistic line that has not been added to the cart yet");continue}n[s].quantity=c.quantity,n[s].quantity===0&&n.splice(s,1),o=true;}else console.warn(`[h2:warn:useOptimisticCart] Tried to update line '${c.id}' but it doesn't exist in the cart`);}}return o&&(r.isOptimistic=o),r.totalQuantity=n.reduce((a,i)=>a+i.quantity,0),r}var Wn="https://raw.githubusercontent.com/Shopify/hydrogen/main/docs/changelog.json";async function jn({request:e,changelogUrl:t}){new URL(e.url).searchParams;return fetch(t||Wn)}var ze="2025-01",me=`Shopify Hydrogen ${Ie}`,Br="30243aa5-17c1-465a-8493-944bcc4e88aa",_="customerAccount",ge="buyer";var M=class extends Response{constructor(t,r,n){super(`Bad request: ${t}`,{status:400,headers:n});}};function we(e,t={}){let r=t.headers?new Headers(t.headers):new Headers({});return r.set("location",e),new Response(null,{status:t.status||302,headers:r})}async function Kn({session:e,customerAccountId:t,customerAccountTokenExchangeUrl:r,httpsOrigin:n,debugInfo:o}){let a=new URLSearchParams,i=e.get(_),c=i?.refreshToken,s=i?.idToken;if(!c)throw new M("Unauthorized","No refreshToken found in the session. Make sure your session is configured correctly and passed to `createCustomerAccountClient`.");a.append("grant_type","refresh_token"),a.append("refresh_token",c),a.append("client_id",t);let u={"content-type":"application/x-www-form-urlencoded","User-Agent":me,Origin:n};new Date().getTime();let l=r,m=await fetch(l,{method:"POST",headers:u,body:a});if(!m.ok){let P=await m.text();throw new Response(P,{status:m.status,headers:{"Content-Type":"text/html; charset=utf-8"}})}let{access_token:y,expires_in:d,refresh_token:g}=await m.json();if(!y||y.length===0)throw new M("Unauthorized","Invalid access token received.");e.set(_,{accessToken:y,expiresAt:new Date(new Date().getTime()+(d-120)*1e3).getTime()+"",refreshToken:g,idToken:s});}function he(e){e.unset(_),e.unset(ge);}async function Gr({locks:e,expiresAt:t,session:r,customerAccountId:n,customerAccountTokenExchangeUrl:o,httpsOrigin:a,debugInfo:i}){if(parseInt(t,10)-1e3<new Date().getTime())try{e.refresh||(e.refresh=Kn({session:r,customerAccountId:n,customerAccountTokenExchangeUrl:o,httpsOrigin:a,debugInfo:i})),await e.refresh,delete e.refresh;}catch(c){throw he(r),c&&c.status!==401?c:new M("Unauthorized","Login before querying the Customer Account API.")}}function Qr(){let e=zn();return jr(e)}async function Wr(e){let t=await crypto.subtle.digest({name:"SHA-256"},new TextEncoder().encode(e)),r=Yn(t);return jr(r)}function zn(){let e=new Uint8Array(32);return crypto.getRandomValues(e),String.fromCharCode.apply(null,Array.from(e))}function jr(e){return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function Yn(e){let t=new Uint8Array(e),r=Array.from(t);return String.fromCharCode(...r)}function Kr(){let e=Date.now().toString(),t=Math.random().toString(36).substring(2);return e+t}async function zr(e,t,r,n,o){let a=t;if(!e)throw new M("Unauthorized","oAuth access token was not provided during token exchange.");let i=new URLSearchParams;i.append("grant_type","urn:ietf:params:oauth:grant-type:token-exchange"),i.append("client_id",a),i.append("audience",Br),i.append("subject_token",e),i.append("subject_token_type","urn:ietf:params:oauth:token-type:access_token"),i.append("scopes","https://api.customers.com/auth/customer.graphql");let c={"content-type":"application/x-www-form-urlencoded","User-Agent":me,Origin:n};new Date().getTime();let u=r,p=await fetch(u,{method:"POST",headers:c,body:i});let l=await p.json();if(l.error)throw new M(l.error_description);return l.access_token}function Yr(e){return Jn(e).payload.nonce}function Jn(e){let[t,r,n]=e.split("."),o=JSON.parse(atob(t)),a=JSON.parse(atob(r));return {header:o,payload:a,signature:n}}function Ye(){return Zn(Xn())}function Xn(){try{return crypto.getRandomValues(new Uint8Array(16))}catch{return new Uint8Array(16).map(()=>Math.random()*255|0)}}function Zn(e){return Array.from(e,function(t){return ("0"+(t&255).toString(16)).slice(-2)}).join("")}function Je(e){if(!e)return;let{pathname:t,search:r}=new URL(e),n=t+r,o=new URLSearchParams(r),a=o.get("return_to")||o.get("redirect");if(a){if(Xr(e,a))return a;console.warn(`Cross-domain redirects are not supported. Tried to redirect from ${n} to ${a}`);}}function Xr(e,t){try{return new URL(e).origin===new URL(t,e).origin}catch{return false}}function Vt({requestUrl:e,defaultUrl:t,redirectUrl:r}){let n=e,o=Jr(e,t),a=r?Jr(e,r):o;return Xr(e,a.toString())?a.toString():(console.warn(`Cross-domain redirects are not supported. Tried to redirect from ${n} to ${a}. Default url ${o} is used instead.`),o.toString())}function Jr(e,t){return ea(t)?new URL(t):new URL(t,new URL(e).origin)}function ea(e){try{return new URL(e),!0}catch{return false}}function Zr(e,t){let r=`https://shopify.com/${t}`,n=`https://shopify.com/authentication/${t}`;return function(a){switch(a){case "CA_BASE_URL":return r;case "CA_BASE_AUTH_URL":return n;case "GRAPHQL":return `${r}/account/customer/api/${e}/graphql`;case "AUTH":return `${n}/oauth/authorize`;case "LOGIN_SCOPE":return t?"openid email customer-account-api:full":"openid email https://api.customers.com/auth/customer.graphql";case "TOKEN_EXCHANGE":return `${n}/oauth/token`;case "LOGOUT":return `${n}/logout`}}}function ta(e,t){if(!e.url)return t;let{pathname:r}=new URL(e.url),n=r.replace(/\.data$/,"").replace(/\/_root$/,"/").replace(/(.+)\/$/,"$1"),o=t+`?${new URLSearchParams({return_to:n}).toString()}`;return we(o)}function Mt({session:e,customerAccountId:t,shopId:r,customerApiVersion:n=ze,request:o,waitUntil:a,authUrl:i,customAuthStatusHandler:c,logErrors:s=true,loginPath:u="/account/login",authorizePath:p="/account/authorize",defaultRedirectPath:l="/account",language:m}){if(n!==ze&&console.warn(`[h2:warn:createCustomerAccountClient] You are using Customer Account API version ${n} when this version of Hydrogen was built for ${ze}.`),e||console.warn("[h2:warn:createCustomerAccountClient] session is required to use Customer Account API. Ensure the session object passed in exist."),!o?.url)throw new Error("[h2:error:createCustomerAccountClient] The request object does not contain a URL.");let y=c||(()=>ta(o,u)),d=new URL(o.url),g=d.protocol==="http:"?d.origin.replace("http","https"):d.origin,P=Vt({requestUrl:g,defaultUrl:p,redirectUrl:i}),f=Zr(n,r),h=ra(f,t),S=f("GRAPHQL"),w={};async function D({query:C,type:A,variables:x={}}){let b=await F();if(!b)throw y();new Date().getTime();let k=await fetch(S,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":me,Origin:g,Authorization:b},body:JSON.stringify({query:C,variables:x})});let J=await k.text(),X={url:S,response:k,type:A,query:C,queryVariables:x,errors:void 0,client:"customer"};if(!k.ok){if(k.status===401)throw he(e),y();let v;try{v=W(J);}catch{v=[{message:J}];}Re({...X,errors:v});}try{let v=W(J),{errors:N}=v,De=N?.map(({message:_e,...tt})=>new se(_e,{...tt,clientOperation:`customerAccount.${X.type}`,requestId:k.headers.get("x-request-id"),queryVariables:x,query:C}));return {...v,...N&&{errors:De}}}catch{Re({...X,errors:[{message:J}]});}}async function L(){if(!r)return false;let C=e.get(_),A=C?.accessToken,x=C?.expiresAt;if(!A||!x)return false;let b=$?.();try{await Gr({locks:w,expiresAt:x,session:e,customerAccountId:t,customerAccountTokenExchangeUrl:f("TOKEN_EXCHANGE"),httpsOrigin:g,debugInfo:{waitUntil:a,stackInfo:b,...ee(o)}});}catch{return false}return true}async function O(){if(!await L())throw y()}async function F(){if(await L())return e.get(_)?.accessToken}async function xe(C,A){return h(),C=fe(C),We(C,"customer.mutate"),le(D({query:C,type:"mutation",...A}),{logErrors:s})}async function oe(C,A){return h(),C=fe(C),Qe(C,"customer.query"),le(D({query:C,type:"query",...A}),{logErrors:s})}function Y(C){e.set(ge,{...e.get(ge),...C});}async function ne(){let C=await F();if(C)return {...e.get(ge),customerAccessToken:C}}return {login:async C=>{h();let A=new URL(f("AUTH")),x=Kr(),b=Ye();A.searchParams.set("client_id",t),A.searchParams.set("scope","openid email"),A.searchParams.append("response_type","code"),A.searchParams.append("redirect_uri",P),A.