@occluze/tether 0.6.7 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +11 -11
  2. package/dist/esm/astro.js +2 -2
  3. package/dist/esm/chunks/account-UIPWJQ3Y.js +1 -0
  4. package/dist/esm/chunks/account-pages-6ROA6Y4V.js +1 -0
  5. package/dist/esm/chunks/analytics-2V632IRV.js +1 -0
  6. package/dist/esm/chunks/chunk-4GCXM764.js +1 -0
  7. package/dist/esm/chunks/chunk-56FCLJJD.js +1 -0
  8. package/dist/esm/chunks/chunk-5Z5O3767.js +1 -0
  9. package/dist/esm/chunks/chunk-6OZJCAGZ.js +1 -0
  10. package/dist/esm/chunks/chunk-A5SYCVQM.js +1 -0
  11. package/dist/esm/chunks/chunk-BA4LQJJQ.js +1 -0
  12. package/dist/esm/chunks/chunk-BFTZR4OB.js +4 -0
  13. package/dist/esm/chunks/chunk-C5JYQCWH.js +1 -0
  14. package/dist/esm/chunks/chunk-E5YO6274.js +1 -0
  15. package/dist/esm/chunks/chunk-MPDWM2NN.js +1 -0
  16. package/dist/esm/chunks/chunk-T44MUL4Y.js +1 -0
  17. package/dist/esm/chunks/chunk-YLUULATY.js +1 -0
  18. package/dist/esm/chunks/diagnose-3FEKRIEK.js +14 -0
  19. package/dist/esm/chunks/extras-6POFBNOP.js +1 -0
  20. package/dist/esm/chunks/markets-ui-FD6NI2OG.js +1 -0
  21. package/dist/esm/chunks/search-UJ73YBQ5.js +1 -0
  22. package/dist/esm/index.js +1 -1
  23. package/dist/esm/server.js +2 -1
  24. package/dist/presets/barba.esm.js +55 -39
  25. package/dist/tether.account-pages.js +781 -495
  26. package/dist/tether.account-pages.min.js +1 -1
  27. package/dist/tether.account.js +462 -381
  28. package/dist/tether.account.min.js +1 -1
  29. package/dist/tether.analytics.js +299 -194
  30. package/dist/tether.analytics.min.js +1 -1
  31. package/dist/tether.diagnose.js +354 -262
  32. package/dist/tether.diagnose.min.js +2 -2
  33. package/dist/tether.extras.js +82 -45
  34. package/dist/tether.extras.min.js +1 -1
  35. package/dist/tether.js +3653 -2116
  36. package/dist/tether.markets.js +238 -150
  37. package/dist/tether.markets.min.js +1 -1
  38. package/dist/tether.min.js +3 -3
  39. package/dist/tether.min.js.map +4 -4
  40. package/dist/tether.search.js +207 -136
  41. package/dist/tether.search.min.js +1 -1
  42. package/dist/types/server/src/shared/account-orders.d.ts +44 -0
  43. package/dist/types/server/src/shared/account-routes.d.ts +153 -0
  44. package/dist/types/server/src/shared/api-versions.d.ts +13 -0
  45. package/dist/types/server/src/shared/error-message.d.ts +2 -0
  46. package/dist/types/server/src/shared/json.d.ts +25 -0
  47. package/dist/types/server/src/shared/market-codes.d.ts +16 -0
  48. package/dist/types/src/account/addresses-view.d.ts +5 -0
  49. package/dist/types/src/account/answers.d.ts +40 -0
  50. package/dist/types/src/account/markup.d.ts +19 -0
  51. package/dist/types/src/account/operations.d.ts +41 -0
  52. package/dist/types/src/account/order-lines.d.ts +13 -0
  53. package/dist/types/src/account/order-list.d.ts +12 -0
  54. package/dist/types/src/account/order-page.d.ts +6 -0
  55. package/dist/types/src/account/page-answers.d.ts +182 -0
  56. package/dist/types/src/account/page-events.d.ts +2 -0
  57. package/dist/types/src/account/server-client.d.ts +60 -0
  58. package/dist/types/src/account/subscriptions-view.d.ts +2 -0
  59. package/dist/types/src/account-api.d.ts +18 -0
  60. package/dist/types/src/account-marks.d.ts +15 -0
  61. package/dist/types/src/account-pages.d.ts +8 -0
  62. package/dist/types/src/account.d.ts +64 -0
  63. package/dist/types/src/amounts.d.ts +12 -0
  64. package/dist/types/src/analytics-shopify.d.ts +41 -0
  65. package/dist/types/src/analytics.d.ts +2 -0
  66. package/dist/types/src/api-version.d.ts +28 -0
  67. package/dist/types/src/astro.d.ts +42 -0
  68. package/dist/types/src/cart/cart-shape.d.ts +43 -0
  69. package/dist/types/src/cart/checkout.d.ts +16 -0
  70. package/dist/types/src/cart/drawer.d.ts +18 -0
  71. package/dist/types/src/cart/mutations.d.ts +79 -0
  72. package/dist/types/src/cart/render.d.ts +17 -0
  73. package/dist/types/src/cart/store.d.ts +182 -0
  74. package/dist/types/src/cart.d.ts +106 -0
  75. package/dist/types/src/client.d.ts +100 -0
  76. package/dist/types/src/collection.d.ts +25 -0
  77. package/dist/types/src/config-sections.d.ts +40 -0
  78. package/dist/types/src/config.d.ts +185 -0
  79. package/dist/types/src/controls/cart-controls.d.ts +2 -0
  80. package/dist/types/src/controls/discount.d.ts +2 -0
  81. package/dist/types/src/controls/extras.d.ts +5 -0
  82. package/dist/types/src/controls/navigation.d.ts +12 -0
  83. package/dist/types/src/diagnose-markup.d.ts +19 -0
  84. package/dist/types/src/diagnose.d.ts +60 -0
  85. package/dist/types/src/dom.d.ts +75 -0
  86. package/dist/types/src/extras.d.ts +21 -0
  87. package/dist/types/src/fragments.d.ts +158 -0
  88. package/dist/types/src/globals.d.ts +15 -0
  89. package/dist/types/src/images.d.ts +20 -0
  90. package/dist/types/src/index.d.ts +167 -0
  91. package/dist/types/src/initial.d.ts +56 -0
  92. package/dist/types/src/lazy.d.ts +28 -0
  93. package/dist/types/src/loader.d.ts +84 -0
  94. package/dist/types/src/market-codes.d.ts +6 -0
  95. package/dist/types/src/markets-ui.d.ts +32 -0
  96. package/dist/types/src/markets.d.ts +72 -0
  97. package/dist/types/src/markup.d.ts +131 -0
  98. package/dist/types/src/mounting.d.ts +46 -0
  99. package/dist/types/src/page-market.d.ts +27 -0
  100. package/dist/types/src/presets/barba.d.ts +56 -0
  101. package/dist/types/src/product-events.d.ts +2 -0
  102. package/dist/types/src/product-render.d.ts +17 -0
  103. package/dist/types/src/product-shape.d.ts +88 -0
  104. package/dist/types/src/product-state.d.ts +110 -0
  105. package/dist/types/src/product.d.ts +66 -0
  106. package/dist/types/src/repeaters.d.ts +16 -0
  107. package/dist/types/src/search.d.ts +33 -0
  108. package/dist/types/src/selling-plans.d.ts +64 -0
  109. package/dist/types/src/server.d.ts +88 -0
  110. package/dist/types/src/shopify-values.d.ts +46 -0
  111. package/dist/types/src/status.d.ts +33 -0
  112. package/dist/types/src/storage.d.ts +12 -0
  113. package/dist/types/src/store-html.d.ts +39 -0
  114. package/dist/types/src/storefront/catalog.d.ts +38 -0
  115. package/dist/types/src/storefront/json-ld.d.ts +20 -0
  116. package/dist/types/src/variant-render.d.ts +14 -0
  117. package/package.json +42 -22
  118. package/src/account/addresses-view.ts +58 -0
  119. package/src/account/answers.ts +79 -0
  120. package/src/account/markup.ts +36 -0
  121. package/src/account/operations.ts +145 -0
  122. package/src/account/order-lines.ts +75 -0
  123. package/src/account/order-list.ts +107 -0
  124. package/src/account/order-page.ts +137 -0
  125. package/src/account/page-answers.ts +317 -0
  126. package/src/account/page-events.ts +253 -0
  127. package/src/account/server-client.ts +183 -0
  128. package/src/account/subscriptions-view.ts +115 -0
  129. package/src/account-api.ts +98 -0
  130. package/src/account-marks.ts +35 -0
  131. package/src/account-pages.ts +81 -0
  132. package/src/account.ts +284 -0
  133. package/src/amounts.ts +64 -0
  134. package/src/analytics-shopify.ts +246 -0
  135. package/src/analytics.ts +315 -0
  136. package/src/api-version.ts +79 -0
  137. package/src/astro.ts +272 -0
  138. package/src/cart/cart-shape.ts +25 -0
  139. package/src/cart/checkout.ts +101 -0
  140. package/src/cart/drawer.ts +125 -0
  141. package/src/cart/mutations.ts +237 -0
  142. package/src/cart/render.ts +266 -0
  143. package/src/cart/store.ts +279 -0
  144. package/src/cart.ts +345 -0
  145. package/src/client.ts +391 -0
  146. package/src/collection.ts +175 -0
  147. package/src/config-sections.ts +284 -0
  148. package/src/config.ts +480 -0
  149. package/src/controls/cart-controls.ts +123 -0
  150. package/src/controls/discount.ts +75 -0
  151. package/src/controls/extras.ts +54 -0
  152. package/src/controls/navigation.ts +77 -0
  153. package/src/diagnose-markup.ts +298 -0
  154. package/src/diagnose.ts +294 -0
  155. package/src/dom.ts +268 -0
  156. package/src/extras.ts +136 -0
  157. package/src/fragments.ts +261 -0
  158. package/src/globals.d.ts +15 -0
  159. package/src/images.ts +91 -0
  160. package/src/index.ts +415 -0
  161. package/src/initial.ts +101 -0
  162. package/src/lazy-iife.ts +197 -0
  163. package/src/lazy.ts +42 -0
  164. package/src/loader.ts +363 -0
  165. package/src/market-codes.ts +6 -0
  166. package/src/markets-ui.ts +227 -0
  167. package/src/markets.ts +246 -0
  168. package/src/markup.ts +127 -0
  169. package/src/mounting.ts +264 -0
  170. package/src/page-market.ts +110 -0
  171. package/src/part-integrity.ts +7 -0
  172. package/src/parts/account-pages.ts +7 -0
  173. package/src/parts/account.ts +7 -0
  174. package/src/parts/analytics.ts +7 -0
  175. package/src/parts/diagnose.ts +7 -0
  176. package/src/parts/extras.ts +7 -0
  177. package/src/parts/markets.ts +7 -0
  178. package/src/parts/search.ts +7 -0
  179. package/src/presets/barba.ts +194 -0
  180. package/src/product-events.ts +115 -0
  181. package/src/product-render.ts +218 -0
  182. package/src/product-shape.ts +49 -0
  183. package/src/product-state.ts +318 -0
  184. package/src/product.ts +308 -0
  185. package/src/repeaters.ts +161 -0
  186. package/src/search.ts +305 -0
  187. package/src/selling-plans.ts +145 -0
  188. package/src/server.ts +211 -0
  189. package/src/shopify-values.ts +91 -0
  190. package/src/status.ts +106 -0
  191. package/src/storage.ts +34 -0
  192. package/src/store-html.ts +359 -0
  193. package/src/storefront/catalog.ts +196 -0
  194. package/src/storefront/json-ld.ts +144 -0
  195. package/src/variant-render.ts +139 -0
  196. package/dist/esm/chunks/account-Q6E2TFEV.js +0 -1
  197. package/dist/esm/chunks/account-pages-UZXR4R5F.js +0 -1
  198. package/dist/esm/chunks/analytics-IJBKATUP.js +0 -1
  199. package/dist/esm/chunks/chunk-4QJKLPYR.js +0 -1
  200. package/dist/esm/chunks/chunk-64TUD3QR.js +0 -1
  201. package/dist/esm/chunks/chunk-AJLPU2JC.js +0 -4
  202. package/dist/esm/chunks/chunk-FIOZPPC5.js +0 -1
  203. package/dist/esm/chunks/chunk-K2YEQAIH.js +0 -1
  204. package/dist/esm/chunks/chunk-KIDH76B7.js +0 -1
  205. package/dist/esm/chunks/chunk-PAYT5ZD7.js +0 -1
  206. package/dist/esm/chunks/chunk-RREHGH4A.js +0 -1
  207. package/dist/esm/chunks/chunk-SSJT43CJ.js +0 -1
  208. package/dist/esm/chunks/chunk-VC46IEJQ.js +0 -1
  209. package/dist/esm/chunks/diagnose-3WVAWNTX.js +0 -14
  210. package/dist/esm/chunks/extras-7I7WJX35.js +0 -1
  211. package/dist/esm/chunks/markets-ui-545XLFTE.js +0 -1
  212. package/dist/esm/chunks/search-NILMGYXG.js +0 -1
  213. package/src/account-pages.js +0 -318
  214. package/src/account.js +0 -385
  215. package/src/analytics.js +0 -232
  216. package/src/api-version.js +0 -35
  217. package/src/astro.js +0 -101
  218. package/src/cart.js +0 -559
  219. package/src/client.js +0 -131
  220. package/src/collection.js +0 -114
  221. package/src/config.js +0 -85
  222. package/src/diagnose.js +0 -246
  223. package/src/dom.js +0 -288
  224. package/src/extras.js +0 -63
  225. package/src/fragments.js +0 -144
  226. package/src/index.js +0 -395
  227. package/src/initial.js +0 -75
  228. package/src/lazy-iife.js +0 -46
  229. package/src/lazy.js +0 -18
  230. package/src/loader.js +0 -198
  231. package/src/markets-ui.js +0 -90
  232. package/src/markets.js +0 -133
  233. package/src/mounting.js +0 -154
  234. package/src/parts/account-pages.js +0 -3
  235. package/src/parts/account.js +0 -3
  236. package/src/parts/analytics.js +0 -3
  237. package/src/parts/diagnose.js +0 -3
  238. package/src/parts/extras.js +0 -3
  239. package/src/parts/markets.js +0 -3
  240. package/src/parts/search.js +0 -3
  241. package/src/presets/barba.js +0 -100
  242. package/src/product.js +0 -570
  243. package/src/search.js +0 -153
  244. package/src/selling-plans.js +0 -94
  245. package/src/server.js +0 -252
  246. package/src/status.js +0 -66
  247. package/types/astro.d.ts +0 -17
  248. package/types/barba.d.ts +0 -16
  249. package/types/index.d.ts +0 -426
  250. package/types/server.d.ts +0 -110
@@ -1 +1 @@
1
- (()=>{var mt=Object.defineProperty;var ht=(t,e)=>{for(var n in e)mt(t,n,{get:e[n],enumerable:!0})};var X={};ht(X,{addresses:()=>$t,customer:()=>W,deleteAddress:()=>Nt,getToken:()=>E,handleCallback:()=>at,isLoggedIn:()=>V,login:()=>ot,logout:()=>ut,mountAccount:()=>qt,order:()=>Pt,orders:()=>it,query:()=>q,render:()=>N,requestReturn:()=>Dt,saveAddress:()=>vt,subscriptionAction:()=>Ot,subscriptions:()=>Lt,updateProfile:()=>Ct});var wt=window.Tether.__core["config.js"],{DEFAULTS:jt,cfg:r,configure:Jt,isConfigured:Bt,log:Y,reportError:k,warn:Gt}=wt;var gt=window.Tether.__core["client.js"],{TetherError:w,endpoint:Mt,gql:zt,request:Ft,unwrap:Ht,withContext:Vt}=gt;var pt=window.Tether.__core["dom.js"],{attr:Xt,busy:Yt,cdnUrl:Qt,dataKey:Zt,emit:A,formatDate:te,formatMoney:Q,formatPercent:ee,get:_,has:ne,hasTemplate:oe,imageUrl:re,notifyLayoutChanged:se,parseJSONAttr:ae,productUrl:ce,qsa:g,readText:ie,repeat:R,repeatKeyed:ue,sameImage:le,scoped:de,sel:d,setImage:j,setSelected:fe,setText:$,setTextTracked:me,show:b,toAttributes:he,watchImages:we}=pt;var yt=window.Tether.__core["cart.js"],{Cart:f,focusables:pe,toLineInput:ye}=yt;var _t=window.Tether.__core["lazy.js"],{coreModules:Se,loadPart:Z}=_t;var L=()=>`${r.prefix}:account:${r.domain}`,K=()=>`${r.prefix}:account-login:${r.domain}`,O=()=>r.account?.remember?window.localStorage:window.sessionStorage,nt=t=>btoa(String.fromCharCode(...new Uint8Array(t))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,""),J=()=>nt(crypto.getRandomValues(new Uint8Array(32))),St=async t=>nt(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t))),U=t=>(r.account?.navigate||(e=>window.location.assign(e)))(t),F=(t,e)=>{try{return JSON.parse(t.getItem(e)||"null")}catch{return null}},D=(t,e,n)=>{try{n?t.setItem(e,JSON.stringify(n)):t.removeItem(e)}catch{}},v=null,i=null,B=null,x=null,m=()=>r.account?.server?new URL(String(r.account.server),window.location.href).href.replace(/\/$/,""):"",M=()=>`${r.prefix}:account-hint:${r.domain}`,I=null;async function P(t,{method:e="GET",body:n}={}){let o=await fetch(`${m()}${t}`,{method:e,credentials:"include",headers:e==="POST"?{"Content-Type":"application/json","X-Tether-Account":"1"}:{},body:n?JSON.stringify(n):void 0}),s=await o.json().catch(()=>({}));if(!o.ok&&o.status!==401)throw new w(`Customer accounts: ${s.error||o.status}`,{status:o.status,userErrors:s.userErrors});return s}async function H(){I||(I=await P("/me"));try{I.loggedIn?window.localStorage.setItem(M(),"1"):window.localStorage.removeItem(M())}catch{}return I}async function C(){if(v)return v;let t=r.account?.shopDomain||r.domain,e=s=>fetch(`https://${t}/.well-known/${s}`).then(a=>{if(!a.ok)throw new w(`Customer accounts: ${s} answered ${a.status}`,{status:a.status});return a.json()}),[n,o]=await Promise.all([e("openid-configuration"),e("customer-account-api")]);return v={...n,graphql:o.graphql_api},v}var Tt=()=>r.account?.callbackUrl||`${window.location.origin}${window.location.pathname}`;function V(){return m()?!!I?.loggedIn:!!(i?.refresh||i?.access&&i.expiresAt>Date.now())}async function ot({returnTo:t=window.location.href,locale:e}={}){if(m()){let h=new URL(`${m()}/login`);h.searchParams.set("returnTo",t);let T=e||r.account.locale||(r.locale||"").split("-")[0];T&&h.searchParams.set("locale",T),r.country&&h.searchParams.set("country",String(r.country).toUpperCase()),U(h.toString());return}if(!r.account?.clientId)throw new w("Customer accounts: set account.clientId",{code:"NOT_CONFIGURED"});let n=await C(),o=J(),s=J(),a=J(),u=Tt();D(window.sessionStorage,K(),{state:o,nonce:s,verifier:a,redirect:u,returnTo:t,at:Date.now()});let c=new URL(n.authorization_endpoint),l={client_id:r.account.clientId,scope:"openid email customer-account-api:full",response_type:"code",redirect_uri:u,state:o,nonce:s,code_challenge:await St(a),code_challenge_method:"S256"},p=e||r.account.locale||(r.locale||"").split("-")[0];p&&(l.locale=p),r.country&&(l.region_country=String(r.country).toUpperCase()),Object.entries(l).forEach(([h,T])=>c.searchParams.set(h,T)),U(c.toString())}async function rt(t){let e=await C(),n=await fetch(r.account.tokenUrl||e.token_endpoint,{method:"POST",body:new URLSearchParams(t)}),o=await n.json().catch(()=>({}));if(!n.ok||!o.access_token)throw new w(`Customer accounts: token ${n.status} ${o.error||""}`.trim(),{status:n.status,code:n.status===400||n.status===401?"SESSION_ENDED":"TOKEN_FAILED"});return o}function kt(t){try{return JSON.parse(atob(t.split(".")[1].replace(/-/g,"+").replace(/_/g,"/")))}catch{return null}}function st(t,e=i){i={access:t.access_token,expiresAt:Date.now()+Math.max(0,(Number(t.expires_in)||3600)-120)*1e3,refresh:t.refresh_token||e?.refresh,idToken:t.id_token||e?.idToken},D(O(),L(),i)}async function at(){let t=new URLSearchParams(window.location.search),e=F(window.sessionStorage,K());if(!e||!t.has("code")&&!t.has("error")||t.get("state")!==e.state)return!1;D(window.sessionStorage,K(),null);let n=new URL(window.location.href);if(["code","state","iss","error","error_description"].forEach(l=>n.searchParams.delete(l)),window.history.replaceState(window.history.state,"",n),t.has("error"))return A("account-error",{error:t.get("error")}),!1;if(Date.now()-e.at>10*6e4)throw new w("Customer accounts: the login took too long, please try again");let o=await rt({grant_type:"authorization_code",client_id:r.account.clientId,redirect_uri:e.redirect,code:t.get("code"),code_verifier:e.verifier}),s=await C(),a=kt(o.id_token||""),u=[].concat(a?.aud||[]);if(!a||a.nonce!==e.nonce||a.iss!==s.issuer||!u.includes(r.account.clientId)||a.exp*1e3<Date.now())throw new w("Customer accounts: the login answer did not check out (nonce/issuer/audience)");st(o,null),await ct(),A("account-login",{});let c=e.returnTo&&new URL(e.returnTo,window.location.href);return c&&c.origin===window.location.origin&&c.href!==n.href&&U(c.href),!0}async function E(){return m()||(i||(i=F(O(),L())),!i)?null:i.access&&i.expiresAt>Date.now()?i.access:i.refresh?(B||(B=(async()=>{try{st(await rt({grant_type:"refresh_token",client_id:r.account.clientId,refresh_token:i.refresh})),await ct()}catch(t){if(t.code==="SESSION_ENDED")z();else throw t}finally{B=null}})()),await B,i?.access||null):(z(),null)}function z(){i=null,x=null,D(O(),L(),null),f.customerAccessToken=null}async function ct(){f.customerAccessToken=i?.access||null,f.id()&&i?.access&&await f.setBuyerIdentity({customerAccessToken:i.access},{create:!1}).catch(t=>k(t,"account cart"))}async function q(t,e={}){if(m())throw new w("Customer accounts in server mode only answer customer() and orders()",{code:"NOT_ALLOWED"});let n=await E();if(!n)throw new w("Not logged in",{code:"NOT_LOGGED_IN"});let o=await C(),s=c=>fetch(o.graphql,{method:"POST",headers:{"Content-Type":"application/json",Authorization:c},body:JSON.stringify({query:t,variables:e})}),a=await s(n);a.status===401&&i?.refresh&&(i.expiresAt=0,a=await s(await E()));let u=await a.json().catch(()=>({}));if(!a.ok||u.errors?.length)throw new w(u.errors?.map(c=>c.message).join(" | ")||`Customer accounts: ${a.status}`,{status:a.status});return u.data}async function W(){if(m()){let e=await H();return e.loggedIn?{...e.customer,emailAddress:{emailAddress:e.customer.email},defaultAddress:{formatted:e.customer.address}}:null}return x||(x=(await q("query TetherCustomer{customer{id firstName lastName displayName emailAddress{emailAddress}defaultAddress{formatted}}}")).customer,x)}async function it({first:t=10}={}){return m()?(await P(`/orders?first=${t}`)).orders||[]:(await q("query TetherOrders($first:Int!){customer{orders(first:$first,sortKey:PROCESSED_AT,reverse:true){nodes{id name processedAt financialStatus fulfillmentStatus statusPageUrl totalPrice{amount currencyCode}lineItems(first:20){nodes{title variantTitle quantity image{url altText}}}}}}}",{first:t})).customer?.orders?.nodes||[]}async function ut({returnTo:t=r.account?.logoutUrl||`${window.location.origin}/`}={}){if(m()){let s=await P("/logout",{method:"POST",body:{returnTo:t,cartId:f.id()}});I={loggedIn:!1};try{window.localStorage.removeItem(M())}catch{}A("account-logout",{}),s.logoutUrl?U(s.logoutUrl):N(document);return}let e=i?.idToken||F(O(),L())?.idToken;if(f.id()&&await f.setBuyerIdentity({customerAccessToken:null},{create:!1}).catch(()=>{}),z(),A("account-logout",{}),!e){N(document);return}let n=await C(),o=new URL(n.end_session_endpoint);o.searchParams.set("id_token_hint",e),o.searchParams.set("post_logout_redirect_uri",t),U(o.toString())}var At=t=>{try{return new URL(t).protocol==="https:"}catch{return!1}},xt=t=>{try{return new Date(t).toLocaleDateString(r.locale||void 0)}catch{return t}};async function N(t=document){let e=m()?!!(await H().catch(()=>({loggedIn:!1}))).loggedIn:V()||!!await E().catch(()=>null);g(t,d("show")).forEach(n=>{let o=_(n,"show");o==="logged-in"&&b(n,e),o==="logged-out"&&b(n,!e)}),g(t,d("account-link")).forEach(n=>{let o=_(n,"account-link"),s=o==="payment"&&(r.account?.paymentUrl||r.account?.subscriptionsUrl)||o==="subscriptions"&&r.account?.subscriptionsUrl;n.setAttribute("href",s||`https://${r.domain}/account`)}),e&&(await lt(t),await Promise.all([It(t),Et.some(n=>g(t,d(n)).length)?dt().then(n=>n.renderPages(t)):null]))}async function It(t){let e=g(t,d("orders"));if(e.length){let n=(a,u)=>g(t,d("show")).forEach(c=>{let l=_(c,"show");l==="orders-loading"&&b(c,a),l==="orders-empty"&&b(c,u)});n(!0,!1);let o=!1,s=await it({first:parseInt(_(e[0],"limit")||"10",10)}).catch(a=>(k(a,"orders"),o=!0,[]));n(!1,!o&&s.length===0),e.forEach(a=>R(a,s,(u,c)=>{let l=c.lineItems?.nodes||[];g(u,d("order-bind")).forEach(p=>{let h=_(p,"order-bind");if(h==="url"){let y=G(c);y&&p.setAttribute("href",y);return}if(h==="image"){let y=l.find(ft=>ft.image)?.image;y&&j(p,y.url,y.altText||l[0]?.title||"");return}let T={name:c.name,date:xt(c.processedAt),total:Q(c.totalPrice),status:c.financialStatus?.toLowerCase(),fulfillment:c.fulfillmentStatus?.toLowerCase(),items:l.map(y=>`${y.quantity}\xD7 ${y.title}`).join(", ")}[h];T!=null&&$(p,T)}),g(u,d("order-lines")).forEach(p=>Ut(p,l)),_(u,"order-bind")==="url"&&G(c)&&u.setAttribute("href",G(c))}))}}var bt=t=>String(t||"").split("/").pop().split("?")[0];function G(t){let e=r.account?.orderUrl;return e?String(e).replace("{id}",encodeURIComponent(bt(t.id))):At(t.statusPageUrl)?t.statusPageUrl:null}function Ut(t,e){R(t,e,(n,o)=>{g(n,d("order-line")).concat(n.matches(d("order-line"))?[n]:[]).forEach(s=>{let a=_(s,"order-line");if(a==="image"){o.image&&j(s,o.image.url,o.image.altText||o.title);return}let u={title:o.title,"variant-title":o.variantTitle||"",quantity:String(o.quantity)}[a];u!=null&&$(s,u)})})}var Et=["order","addresses","subscriptions","profile-form","address-form"],tt=null;async function lt(t){let e=g(t,d("account-bind"));if(!e.length)return;let n=await W().catch(o=>(k(o,"account"),null));e.forEach(o=>{let s={"first-name":n?.firstName,"last-name":n?.lastName,name:n?.displayName,email:n?.emailAddress?.emailAddress,address:n?.defaultAddress?.formatted?.join(", ")}[_(o,"account-bind")];s!=null&&$(o,s)})}function dt(){return tt||(tt=Z("account-pages").then(t=>(t.setup({server:m,serverFetch:P,query:q,customer:W,bindCustomer:lt,reset:()=>{x=null,I=null}}),t))),tt}var S=t=>(...e)=>dt().then(n=>n[t](...e)),Pt=S("order"),Ct=S("updateProfile"),$t=S("addresses"),vt=S("saveAddress"),Nt=S("deleteAddress"),Lt=S("subscriptions"),Ot=S("subscriptionAction"),Dt=S("requestReturn"),et=!1;async function qt(t=document){if(!et){if(et=!0,document.addEventListener("click",e=>{let n=e.target;n.closest?.(d("account-login"))?(e.preventDefault(),ot().catch(o=>k(o,"login"))):n.closest?.(d("account-logout"))&&(e.preventDefault(),ut().catch(o=>k(o,"logout")))}),m()){let e=new URL(window.location.href);e.searchParams.get("account")&&(e.searchParams.delete("account"),window.history.replaceState(window.history.state,"",e),A("account-login",{})),f.beforeCheckout=async()=>{if(!(await H()).loggedIn||!f.id())return null;let n=await P("/cart",{method:"POST",body:{cartId:f.id()}}).catch(()=>null);return n?.checkoutUrl?`${n.checkoutUrl}${n.checkoutUrl.includes("?")?"&":"?"}logged_in=true`:null}}else{try{await at()}catch(e){k(e,"login")}!f.customerAccessToken&&await E().catch(()=>null)&&(f.customerAccessToken=i.access)}Y("account",V()?"logged in":"logged out")}await N(t)}window.Tether.__parts.account=X;})();
1
+ (()=>{var Tt=Object.defineProperty;var Pt=(t,e)=>{for(var r in e)Tt(t,r,{get:e[r],enumerable:!0})};var j={};Pt(j,{addresses:()=>ee,customer:()=>F,deleteAddress:()=>ne,isLoggedIn:()=>ht,login:()=>yt,logout:()=>At,mountAccount:()=>ue,order:()=>Qt,orders:()=>xt,render:()=>_,requestReturn:()=>ie,saveAddress:()=>re,subscriptionAction:()=>se,subscriptions:()=>oe,updateProfile:()=>te});var St=window.Tether.__core["config.ts"],[u,de,V,me,fe,h,ge]=St;var Lt=window.Tether.__core["client.ts"],[we,he,ye,xe,g]=Lt;var bt=window.Tether.__core["dom.ts"],[Oe,ke,Te,k,B,T,m,Pe,Se,Le,be,Ee,l,R,c,I,x,P]=bt;var Et=window.Tether.__core["cart.ts"],[S]=Et;var Rt=window.Tether.__core["lazy.ts"],[G]=Rt;function L(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function a(t,e){return L(t)?t[e]:void 0}function M(t){return Array.isArray(t)?t:[]}function i(t){return typeof t=="string"&&t!==""?t:null}var It=t=>typeof t=="number"&&Number.isFinite(t)?t:null,J=t=>It(t)??0,N=(t,e)=>M(t).map(r=>e(r)),K=(t,e)=>({nodes:N(a(t,"nodes"),e)}),D=t=>N(t,i).filter(e=>e!==null);function z(t){return t instanceof Error?t.message:String(t)}function W(t,e,r="localStorage"){try{window[r].setItem(t,e)}catch{}}function $(t,e="localStorage"){try{window[e].removeItem(t)}catch{}}var q=()=>`${u.prefix}:account-hint:${u.domain}`;var X=t=>t==="in"||t==="expired"||t==="error";function Nt(t){let e=i(a(t,"amount")),r=i(a(t,"currencyCode"));return e===null||r===null?null:{amount:e,currencyCode:r}}function vt(t){let e=i(a(t,"url"));return e===null?null:{url:e,altText:i(a(t,"altText"))}}var Ct=t=>({title:i(a(t,"title")),variantTitle:i(a(t,"variantTitle")),quantity:J(a(t,"quantity")),image:vt(a(t,"image"))}),Ut=(t,e)=>({id:e,name:i(a(t,"name")),processedAt:i(a(t,"processedAt")),financialStatus:i(a(t,"financialStatus")),fulfillmentStatus:i(a(t,"fulfillmentStatus")),statusPageUrl:i(a(t,"statusPageUrl")),totalPrice:Nt(a(t,"totalPrice")),lineItems:K(a(t,"lineItems"),Ct)});function Z(t){let e=[];for(let r of M(t)){let n=i(a(r,"id"));if(n===null)return{kind:"missing-id"};e.push(Ut(r,n))}return{kind:"read",orders:e}}var _t=t=>new g(`Customer accounts: the answer has no ${t}`);function Y(t){let e=L(t)?t:{},r=i(e.id),n=i(e.email),o=e.address;return{...r===null?{}:{id:r},firstName:i(e.firstName),lastName:i(e.lastName),displayName:i(e.displayName),emailAddress:n===null?null:{emailAddress:n},defaultAddress:Array.isArray(o)?{formatted:D(o)}:null}}function Q(t){let e=Z(t);if(e.kind==="missing-id")throw _t("order id");return e.orders}function Mt(t){let e=i(a(t,"message"));if(e===null)return null;let r=a(t,"field");return{message:e,field:Array.isArray(r)?D(r):null,code:i(a(t,"code"))}}var tt=t=>N(t,Mt).filter(e=>e!==null);var y=null;function et(){let t=u.account?.server;if(!t)throw new g("Customer accounts need the Worker: set account.server",{code:"NOT_CONFIGURED"});return new URL(t,window.location.href).href.replace(/\/$/,"")}function rt(t){t?W(q(),"1"):$(q())}async function Dt(t,e){try{return await fetch(t,e)}catch(r){throw new g(`Network error: ${z(r)}`,{code:"NETWORK"})}}async function $t(t){let e;try{e=await t.json()}catch{return{}}return L(e)?e:{}}async function A(t,{method:e="GET",body:r}={}){let n={method:e,credentials:"include"};e==="POST"&&(n.headers={"Content-Type":"application/json","X-Tether-Account":"1"}),r&&(n.body=JSON.stringify(r));let o=await Dt(`${et()}${t}`,n);if(o.status===401)return{kind:"logged-out"};let s=await $t(o);if(!o.ok){let d=i(s.error)??String(o.status),p=tt(s.userErrors);throw new g(`Customer accounts: ${d}`,{status:o.status,...p.length>0&&{userErrors:p},...s.code==="INVALID"&&{code:"INVALID"}})}return{kind:"answer",data:s}}async function v(){if(!y){let t=await A("/me");y=t.kind==="answer"&&t.data.loggedIn===!0?{loggedIn:!0,customer:Y(t.data.customer)}:{loggedIn:!1}}return rt(y.loggedIn),y}var nt=()=>y?.loggedIn===!0;function ot(){y=null}function st(t){let e=u.account?.navigate;e?e(t):window.location.assign(t)}var qt=t=>t||u.account?.locale||(u.locale||"").split("-")[0]||"";function it({returnTo:t,locale:e}){let r=new URL(`${et()}/login`);r.searchParams.set("returnTo",t);let n=qt(e);n&&r.searchParams.set("locale",n),u.country&&r.searchParams.set("country",u.country.toUpperCase()),st(r.toString())}async function at(){let t=S.id();if(!(await v()).loggedIn||!t)return null;let e=await A("/cart",{method:"POST",body:{cartId:t}});return e.kind==="logged-out"?null:i(e.data.checkoutUrl)}async function ct(t){let e=await A("/logout",{method:"POST",body:{returnTo:t,cartId:S.id()}});y=null,rt(!1),k("account-logout",{});let r=e.kind==="answer"?i(e.data.logoutUrl):null;return r?(st(r),"redirected"):"stayed"}var Ft=window.Tether.__core["shopify-values.ts"],[ut]=Ft;function b(t,e,r){l(t,c(e)).forEach(n=>{let o=m(n,e)??"";Object.hasOwn(r,o)&&P(n,r[o]===!0)})}var lt=(t,e)=>l(t,c(e)).concat(t.matches(c(e))?[t]:[]);var O=(t,e)=>Object.hasOwn(t,e)?t[e]:void 0;var jt=(t,e)=>({title:t.title||t.name||"","variant-title":t.variantTitle||"",quantity:String(t.quantity),price:T(t.price),total:T(t.totalPrice),sku:t.sku||"",returnable:e===null?void 0:String(e)}),Ht=t=>t.tagName==="INPUT";function Vt(t,e,r){b(t,"order-line-show",{returnable:r>0}),l(t,c("return-quantity")).forEach(n=>{Ht(n)&&(n.max=String(r),n.min="0",n.value||(n.value="0"),n.disabled=r<1)}),l(t,`select${c("return-reason")}`).forEach(n=>{n.dataset.tetherFilled!==e.id&&(n.dataset.tetherFilled=e.id,(e.suggestedReturnReasonDefinitions?.nodes??[]).forEach(o=>{n.appendChild(new Option(o.name??"",o.id))}))})}function dt(t,e,r){R(t,e,(n,o)=>{let s=o.id,d=r&&s?r.get(s)??0:null;s&&(n.dataset.tetherLine=s);let p=jt(o,d);lt(n,"order-line").forEach(w=>{let E=m(w,"order-line")??"";if(E==="image"){o.image&&I(w,o.image.url,o.image.altText||o.title||"");return}let H=O(p,E);H!==void 0&&x(w,H)}),s&&d!==null&&Vt(n,{...o,id:s},d)})}var C=10,U=50,mt=t=>typeof t=="number"&&Number.isInteger(t)&&t>=1&&t<=U;function Bt(t){let e=Number.parseInt(t||String(C),10)||C;return Math.min(Math.max(e,1),U)}var Gt=t=>t.replace(/\?.*$/,"").replace(/^.*\//,"");function Jt(t){let e=u.account?.orderUrl;if(e)return e.replaceAll("{id}",encodeURIComponent(Gt(t.id)));let r=t.statusPageUrl;return r!==null&&ut(r)?r:null}var Kt=t=>({name:t.name??"",date:B(t.processedAt),total:T(t.totalPrice),status:t.financialStatus?.toLowerCase(),fulfillment:t.fulfillmentStatus?.toLowerCase(),items:t.lineItems.nodes.map(e=>`${String(e.quantity)}\xD7 ${e.title??""}`).join(", ")});function zt(t,e){let r=e.lineItems.nodes,n=Jt(e),o=Kt(e);l(t,c("order-bind")).forEach(s=>{let d=m(s,"order-bind")??"";if(d==="url"){n&&s.setAttribute("href",n);return}if(d==="image"){let w=r.find(E=>E.image)?.image;w&&I(s,w.url,w.altText||r[0]?.title||"");return}let p=O(o,d);p!==void 0&&x(s,p)}),l(t,c("order-lines")).forEach(s=>{dt(s,r,null)}),m(t,"order-bind")==="url"&&n&&t.setAttribute("href",n)}async function ft(t,e){let r=l(t,c("orders")),n=r[0];if(!n)return;b(t,"show",{"orders-loading":!0,"orders-empty":!1});let o=Bt(m(n,"limit")),s;try{s=await e(o)}catch(d){h(d,"orders"),s=null}b(t,"show",{"orders-loading":!1,"orders-empty":s?.length===0}),r.forEach(d=>{R(d,s??[],zt)})}var Wt=["order","addresses","subscriptions","profile-form","address-form"],ht=nt;function yt({returnTo:t=window.location.href,locale:e}={}){return new Promise(r=>{it({returnTo:t,locale:e}),r()})}async function F(){let t=await v();return t.loggedIn?t.customer:null}async function xt({first:t=C}={}){if(!mt(t))throw new g(`Customer accounts: orders() takes first from 1 to ${String(U)}`,{code:"INVALID"});let e=await A(`/orders?${new URLSearchParams({first:String(t)}).toString()}`);return e.kind==="logged-out"?[]:Q(e.data.orders)}async function At({returnTo:t=u.account?.logoutUrl||`${window.location.origin}/`}={}){await ct(t)==="stayed"&&await _(document)}async function Xt(){try{return(await v()).loggedIn?{kind:"logged-in"}:{kind:"logged-out"}}catch(t){return{kind:"unknown",error:t}}}var gt=t=>Wt.some(e=>l(t,c(e)).length>0);function Zt(t){l(t,c("account-link")).forEach(e=>{e.setAttribute("href",Yt(m(e,"account-link")))})}function Yt(t){let e=u.account,r=`https://${u.domain}/account`;return t==="payment"?e?.paymentUrl||e?.subscriptionsUrl||r:t==="subscriptions"&&e?.subscriptionsUrl||r}async function _(t=document){let e=await Xt();e.kind==="unknown"&&h(e.error,"account");let r=e.kind==="logged-in";if(l(t,c("show")).forEach(n=>{let o=m(n,"show");o==="logged-in"&&P(n,r),o==="logged-out"&&P(n,!r)}),Zt(t),e.kind==="unknown"&&gt(t)){(await f()).showUnavailable(t);return}r&&(await Ot(t),await Promise.all([ft(t,n=>xt({first:n})),gt(t)?f().then(n=>n.renderPages(t)):null]))}async function Ot(t){let e=l(t,c("account-bind"));if(!e.length)return;let r;try{r=await F()}catch(o){h(o,"account");return}if(!r)return;let n={"first-name":r.firstName,"last-name":r.lastName,name:r.displayName,email:r.emailAddress?.emailAddress,address:r.defaultAddress?.formatted.join(", ")};e.forEach(o=>{let s=O(n,m(o,"account-bind")??"");s!=null&&x(o,s)})}var pt=null;function f(){return pt??(pt=G("account-pages").then(t=>(t.setup({serverFetch:A,customer:F,bindCustomer:Ot,reset:ot}),t))),pt}var Qt=t=>f().then(e=>e.order(t)),te=t=>f().then(e=>e.updateProfile(t)),ee=()=>f().then(t=>t.addresses()),re=(t,e)=>f().then(r=>r.saveAddress(t,e)),ne=t=>f().then(e=>e.deleteAddress(t)),oe=()=>f().then(t=>t.subscriptions()),se=(t,e)=>f().then(r=>r.subscriptionAction(t,e)),ie=(t,e)=>f().then(r=>r.requestReturn(t,e));function ae(t){let e=t.target;e instanceof window.Element&&(e.closest(c("account-login"))?(t.preventDefault(),yt().catch(r=>{h(r,"login")})):e.closest(c("account-logout"))&&(t.preventDefault(),At().catch(r=>{h(r,"logout")})))}function ce(){let t=new URL(window.location.href),e=t.searchParams.get("account");if(X(e))switch(t.searchParams.delete("account"),window.history.replaceState(window.history.state,"",t),e){case"in":k("account-login",{});break;case"expired":case"error":k("account-error",{error:e});break}}var wt=!1;async function ue(t=document){if(wt){await _(t);return}wt=!0,document.addEventListener("click",ae),ce(),S.setCheckoutResolver(at),await _(t),V("account",ht()?"logged in":"logged out")}var{Tether:kt}=window;if(!kt)throw new Error("tether.account.js runs after the Tether script, which loads it");kt.__parts.account=j;})();
@@ -5,255 +5,360 @@
5
5
  __defProp(target, name, { get: all[name], enumerable: true });
6
6
  };
7
7
 
8
- // src/analytics.js
8
+ // src/analytics.ts
9
9
  var analytics_exports = {};
10
10
  __export(analytics_exports, {
11
11
  startAnalytics: () => startAnalytics
12
12
  });
13
13
 
14
- // tether-core:config.js
15
- var m = window.Tether.__core["config.js"];
16
- var { DEFAULTS, cfg, configure, isConfigured, log, reportError, warn } = m;
14
+ // tether-core:config.ts
15
+ var m = window.Tether.__core["config.ts"];
16
+ var [cfg, isConfigured, log, MARKET_SOURCES, parseMarkets, reportError, warn] = m;
17
17
 
18
- // tether-core:client.js
19
- var m2 = window.Tether.__core["client.js"];
20
- var { TetherError, endpoint, gql, request, unwrap, withContext } = m2;
18
+ // tether-core:dom.ts
19
+ var m2 = window.Tether.__core["dom.ts"];
20
+ var [ANALYTICS_EVENTS, attr, attributesFromJson, emit, formatDate, formatMoney, get, has, hasTemplate, isOwnEvent, parseJSONAttr, productUrl, qsa, repeat, sel, setImage, setText, show] = m2;
21
21
 
22
- // tether-core:dom.js
23
- var m3 = window.Tether.__core["dom.js"];
24
- var { attr, busy, cdnUrl, dataKey, emit, formatDate, formatMoney, formatPercent, get, has, hasTemplate, imageUrl, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, readText, repeat, repeatKeyed, sameImage, scoped, sel, setImage, setSelected, setText, setTextTracked, show, toAttributes, watchImages } = m3;
22
+ // tether-core:cart.ts
23
+ var m3 = window.Tether.__core["cart.ts"];
24
+ var [Cart] = m3;
25
25
 
26
- // tether-core:cart.js
27
- var m4 = window.Tether.__core["cart.js"];
28
- var { Cart, focusables, toLineInput } = m4;
26
+ // tether-core:product.ts
27
+ var m4 = window.Tether.__core["product.ts"];
28
+ var [scopes] = m4;
29
29
 
30
- // src/analytics.js
31
- var num = (m5) => m5 ? parseFloat(m5.amount) : 0;
32
- var id = (gid) => String(gid || "").split("/").pop();
33
- function itemFromVariant(p, v, quantity = 1, index) {
34
- return {
35
- item_id: v?.sku || id(v?.id) || id(p.id),
36
- item_name: p.title,
37
- item_variant: v?.title === "Default Title" ? void 0 : v?.title,
38
- item_brand: p.vendor || void 0,
39
- item_category: p.productType || void 0,
40
- price: num(v?.price || p.priceRange?.minVariantPrice),
41
- quantity,
42
- ...index != null ? { index } : {}
43
- };
30
+ // tether-core:client.ts
31
+ var m5 = window.Tether.__core["client.ts"];
32
+ var [endpoint, gql, orNull, shaped, TetherError] = m5;
33
+
34
+ // src/analytics-shopify.ts
35
+ var BUFFER_SIZE = 500;
36
+ var CONSENT_SCRIPTS = {
37
+ "default-banner": "https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js",
38
+ other: "https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js"
39
+ };
40
+ var ANALYTICS_SCRIPT = "https://cdn.shopify.com/storefront/analytics/shopify.js";
41
+ var page = () => window;
42
+ var shopifyGlobal = () => page().Shopify;
43
+ function shopifyOptions() {
44
+ const shopify = cfg.analytics?.shopify;
45
+ return typeof shopify === "object" ? shopify : {};
44
46
  }
45
- function itemFromLine(l, quantity = l.quantity) {
46
- const m5 = l.merchandise || {};
47
- return itemFromVariant({ ...m5.product || {}, title: m5.product?.title }, m5, quantity);
47
+ function trackingAllowed() {
48
+ try {
49
+ const privacy = shopifyGlobal()?.customerPrivacy;
50
+ return privacy?.consentStatus === "loaded" && privacy.currentVisitorConsent?.()?.analytics !== "no" && Boolean(privacy.analyticsProcessingAllowed?.());
51
+ } catch {
52
+ return false;
53
+ }
48
54
  }
49
- var value = (items) => Math.round(items.reduce((s, i) => s + (i.price || 0) * (i.quantity || 1), 0) * 100) / 100;
50
- function ga(event, ecommerce) {
51
- const name = typeof cfg.analytics.dataLayer === "string" ? cfg.analytics.dataLayer : "dataLayer";
52
- const dl = window[name] = window[name] || [];
53
- if (ecommerce) dl.push({ ecommerce: null });
54
- dl.push(ecommerce ? { event, ecommerce } : { event });
55
+ function destinationContext(name) {
56
+ const tag = `hydrogen:${name}`;
57
+ return {
58
+ getTrackingValues: () => {
59
+ const internal = trackingAllowed() ? shopifyGlobal()?.customerPrivacy?.__internal : void 0;
60
+ return {
61
+ uniqueToken: internal?.uniqueToken?.({ generateFallback: true, tag }) ?? "",
62
+ visitToken: internal?.visitToken?.({ generateFallback: true, tag }) ?? ""
63
+ };
64
+ }
65
+ };
55
66
  }
56
- var bus = null;
57
- function shopifyBus(shopId) {
67
+ var subscriberOf = (destination) => (event, subscriber) => {
68
+ const subscribers = destination.subscribers.get(event) ?? /* @__PURE__ */ new Set();
69
+ destination.subscribers.set(event, subscribers);
70
+ subscribers.add(subscriber);
71
+ return () => destination.subscribers.get(event)?.delete(subscriber);
72
+ };
73
+ function createBus(shopId) {
58
74
  const destinations = [];
59
75
  const buffer = [];
60
- const privacy = () => window.Shopify?.customerPrivacy;
61
- const canTrack = () => {
62
- try {
63
- const p = privacy();
64
- return p?.consentStatus === "loaded" && p.currentVisitorConsent?.()?.analytics !== "no" && Boolean(p.analyticsProcessingAllowed?.());
65
- } catch {
66
- return false;
67
- }
76
+ const config = {
77
+ shop: { shopId, channel: "headless" },
78
+ consent: { mode: shopifyOptions().consent || "no-banner" }
68
79
  };
69
- const config = { shop: { shopId, channel: "headless" }, consent: { mode: cfg.analytics.shopify?.consent || "no-banner" } };
70
80
  const deliver = () => {
71
- if (!canTrack()) return;
72
- destinations.forEach((d) => {
73
- while (d.next < buffer.length) {
74
- const { event, payload } = buffer[d.next++];
75
- (d.subs.get(event) || []).forEach((cb) => {
76
- try {
77
- cb(payload, d.context);
78
- } catch (err) {
79
- reportError(err, `analytics ${d.name}`);
80
- }
81
- });
81
+ if (!trackingAllowed()) return;
82
+ for (const destination of destinations) {
83
+ for (; destination.next < buffer.length; destination.next += 1) {
84
+ const buffered = buffer[destination.next];
85
+ if (buffered) deliverTo(destination, buffered);
82
86
  }
83
- });
87
+ }
84
88
  };
85
- const api = {
89
+ const bus2 = {
86
90
  getConfig: () => config,
87
91
  publish(event, payload = {}) {
88
92
  buffer.push({ event, payload: { shop: config.shop, url: window.location.href, ...payload } });
89
- if (buffer.length > 500) {
93
+ if (buffer.length > BUFFER_SIZE) {
90
94
  buffer.shift();
91
- destinations.forEach((d) => {
92
- d.next = Math.max(0, d.next - 1);
93
- });
95
+ for (const destination of destinations) destination.next = Math.max(0, destination.next - 1);
94
96
  }
95
97
  deliver();
96
98
  },
97
- addDestination(dest) {
98
- const tag = `hydrogen:${dest.name}`;
99
- const d = {
100
- name: dest.name,
99
+ addDestination(spec) {
100
+ const destination = {
101
+ name: spec.name,
101
102
  next: 0,
102
- subs: /* @__PURE__ */ new Map(),
103
- context: {
104
- getTrackingValues: () => {
105
- const i = canTrack() ? privacy()?.__internal : null;
106
- return { uniqueToken: i?.uniqueToken?.({ generateFallback: true, tag }) ?? "", visitToken: i?.visitToken?.({ generateFallback: true, tag }) ?? "" };
107
- }
108
- }
103
+ subscribers: /* @__PURE__ */ new Map(),
104
+ context: destinationContext(spec.name)
109
105
  };
110
- const subscribe = (event, cb) => {
111
- if (!d.subs.has(event)) d.subs.set(event, /* @__PURE__ */ new Set());
112
- d.subs.get(event).add(cb);
113
- return () => d.subs.get(event)?.delete(cb);
114
- };
115
- Promise.resolve(dest.setup?.({ subscribe, getConfig: api.getConfig })).then(() => {
116
- destinations.push(d);
106
+ Promise.resolve(spec.setup?.({ subscribe: subscriberOf(destination), getConfig: bus2.getConfig })).then(() => {
107
+ destinations.push(destination);
117
108
  deliver();
118
- }).catch((err) => reportError(err, `analytics ${dest.name}`));
109
+ }).catch((error) => {
110
+ reportError(error, `analytics ${spec.name}`);
111
+ });
119
112
  return () => {
120
- const i = destinations.indexOf(d);
121
- if (i >= 0) destinations.splice(i, 1);
113
+ const index = destinations.indexOf(destination);
114
+ if (index >= 0) destinations.splice(index, 1);
122
115
  };
123
116
  }
124
117
  };
125
118
  document.addEventListener("consentTrackingApiLoaded", deliver);
126
119
  document.addEventListener("visitorConsentCollected", deliver);
127
- return api;
120
+ return bus2;
121
+ }
122
+ function deliverTo(destination, { event, payload }) {
123
+ destination.subscribers.get(event)?.forEach((subscriber) => {
124
+ try {
125
+ subscriber(payload, destination.context);
126
+ } catch (error) {
127
+ reportError(error, `analytics ${destination.name}`);
128
+ }
129
+ });
128
130
  }
129
131
  function loadScript(src) {
130
- const s = document.createElement("script");
131
- s.src = src;
132
- s.async = true;
133
- document.head.appendChild(s);
132
+ const script = document.createElement("script");
133
+ script.src = src;
134
+ script.async = true;
135
+ document.head.appendChild(script);
134
136
  }
135
- async function startShopify() {
136
- if (window.Shopify?.analytics) {
137
- bus = window.Shopify.analytics;
138
- return;
139
- }
140
- const data = await gql("query TetherShopId { shop { id } }", {}, { context: false });
141
- const country = String(cfg.country || "US").toUpperCase();
142
- const S = window.Shopify = window.Shopify || {};
143
- Object.assign(S, {
144
- country,
145
- locale: (cfg.locale || "en").split("-")[0].toLowerCase(),
146
- // required by Shopify's script
147
- shop: cfg.domain,
148
- routes: { root: "/", match: () => ({ pageTemplateName: mainProduct() ? "product" : "page" }), ...S.routes || {} }
149
- });
150
- const proxy = cfg.analytics.shopify?.proxy;
151
- S.customerPrivacy = {
152
- ...S.customerPrivacy || {},
137
+ async function startShopifyAnalytics(isProductPage) {
138
+ const existing = shopifyGlobal();
139
+ if (existing?.analytics) return existing.analytics;
140
+ const data = await gql(
141
+ "query TetherShopId { shop { id } }",
142
+ {},
143
+ shaped({ shop: { id: "string" } }),
144
+ { context: false }
145
+ );
146
+ const shopify = shopifyGlobal() ?? {};
147
+ page().Shopify = shopify;
148
+ shopify.country = cfg.country ?? "US";
149
+ const [language = "en"] = (cfg.locale || "en").split("-");
150
+ shopify.locale = language.toLowerCase();
151
+ shopify.shop = cfg.domain;
152
+ shopify.routes = {
153
+ root: "/",
154
+ match: () => ({ pageTemplateName: isProductPage() ? "product" : "page" }),
155
+ ...shopify.routes
156
+ };
157
+ const { proxy, consent } = shopifyOptions();
158
+ shopify.customerPrivacy = {
159
+ ...shopify.customerPrivacy,
153
160
  config: proxy ? { isHeadless: true, asyncConsent: true, asyncVisitorState: true, consentDomain: window.location.host } : { isHeadless: true, storefrontAccessToken: cfg.token, checkoutRootDomain: cfg.domain }
154
161
  };
155
- bus = shopifyBus(data.shop.id);
156
- S.analytics = bus;
157
- loadScript(cfg.analytics.shopify?.consent === "default-banner" ? "https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js" : "https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js");
158
- loadScript("https://cdn.shopify.com/storefront/analytics/shopify.js");
162
+ const bus2 = createBus(data.shop.id);
163
+ shopify.analytics = bus2;
164
+ loadScript(consent === "default-banner" ? CONSENT_SCRIPTS["default-banner"] : CONSENT_SCRIPTS.other);
165
+ loadScript(ANALYTICS_SCRIPT);
159
166
  log("shopify analytics ready", data.shop.id);
167
+ return bus2;
168
+ }
169
+
170
+ // src/analytics.ts
171
+ var DEFAULT_VARIANT_TITLE = "Default Title";
172
+ var CENTS_PER_UNIT = 100;
173
+ var MAX_LIST_ITEMS = 200;
174
+ var amountOf = (money) => money ? parseFloat(money.amount) : 0;
175
+ var numericId = (gid) => (gid ?? "").split("/").pop() ?? "";
176
+ function itemFromVariant(product, variant, quantity = 1, index) {
177
+ const item = {
178
+ item_id: variant?.sku || numericId(variant?.id) || numericId(product.id),
179
+ item_name: product.title,
180
+ item_variant: variant?.title === DEFAULT_VARIANT_TITLE ? void 0 : variant?.title,
181
+ item_brand: product.vendor || void 0,
182
+ item_category: product.productType || void 0,
183
+ price: amountOf(variant?.price ?? product.priceRange?.minVariantPrice),
184
+ quantity
185
+ };
186
+ if (index != null) item.index = index;
187
+ return item;
188
+ }
189
+ var itemFromLine = (line, quantity = line.quantity) => itemFromVariant(line.merchandise.product, line.merchandise, quantity);
190
+ function totalValue(items) {
191
+ const total = items.reduce((sum, item) => sum + item.price * (item.quantity || 1), 0);
192
+ return Math.round(total * CENTS_PER_UNIT) / CENTS_PER_UNIT;
160
193
  }
161
- var productPayload = (p, v, quantity = 1) => ({
162
- id: p.id,
163
- title: p.title,
164
- price: v.price,
165
- vendor: p.vendor || "",
166
- variantId: v.id,
167
- variantTitle: v.title,
194
+ var productPayload = (product, variant, quantity = 1) => ({
195
+ id: product.id,
196
+ title: product.title,
197
+ price: variant.price,
198
+ vendor: product.vendor || "",
199
+ variantId: variant.id,
200
+ variantTitle: variant.title,
168
201
  quantity,
169
- sku: v.sku || void 0,
170
- productType: p.productType || void 0
202
+ sku: variant.sku || void 0,
203
+ productType: product.productType || void 0
171
204
  });
172
- function analyticsLine(l) {
173
- const m5 = l.merchandise || {};
174
- return { id: l.id, quantity: l.quantity, merchandise: { id: m5.id, title: m5.title, price: m5.price, sku: m5.sku, product: { id: m5.product?.id, title: m5.product?.title, vendor: m5.product?.vendor || "", handle: m5.product?.handle } } };
205
+ var linePayload = (line) => ({
206
+ id: line.id,
207
+ quantity: line.quantity,
208
+ merchandise: {
209
+ id: line.merchandise.id,
210
+ title: line.merchandise.title,
211
+ price: line.merchandise.price,
212
+ sku: line.merchandise.sku,
213
+ product: {
214
+ id: line.merchandise.product.id,
215
+ title: line.merchandise.product.title,
216
+ vendor: line.merchandise.product.vendor || "",
217
+ handle: line.merchandise.product.handle
218
+ }
219
+ }
220
+ });
221
+ function dataLayer() {
222
+ const { dataLayer: option } = cfg.analytics ?? {};
223
+ const name = typeof option === "string" ? option : "dataLayer";
224
+ const existing = Reflect.get(window, name);
225
+ if (Array.isArray(existing)) return existing;
226
+ const created = [];
227
+ Reflect.set(window, name, created);
228
+ return created;
175
229
  }
176
- function mainProduct() {
177
- const el = document.querySelector(sel("product"));
178
- return el && !el.closest(`${sel("collection")},${sel("products")},${sel("recommendations")}`) ? window.Tether?.getScope(el) : null;
230
+ function pushToDataLayer(event, ecommerce) {
231
+ const layer = dataLayer();
232
+ if (!ecommerce) {
233
+ layer.push({ event });
234
+ return;
235
+ }
236
+ layer.push({ ecommerce: null });
237
+ layer.push({ event, ecommerce });
179
238
  }
180
- var send = (name, data, shopifyEvent, shopifyPayload) => {
181
- if (cfg.analytics.dataLayer) ga(name, data);
239
+ var bus = null;
240
+ var lastLines = null;
241
+ var lastCart = null;
242
+ var viewed = /* @__PURE__ */ new WeakSet();
243
+ function send(name, data, shopifyEvent, shopifyPayload) {
244
+ if (cfg.analytics?.dataLayer) pushToDataLayer(name, data);
182
245
  if (bus && shopifyEvent) bus.publish(shopifyEvent, shopifyPayload);
183
246
  try {
184
- cfg.analytics.onEvent?.(name, data);
185
- } catch (err) {
186
- reportError(err, "analytics onEvent");
247
+ cfg.analytics?.onEvent?.(name, data);
248
+ } catch (error) {
249
+ reportError(error, "analytics onEvent");
250
+ }
251
+ }
252
+ function mainProduct() {
253
+ const el = document.querySelector(sel("product"));
254
+ if (!el || el.closest(`${sel("collection")},${sel("products")},${sel("recommendations")}`)) return null;
255
+ return scopes.get(el) ?? null;
256
+ }
257
+ function onProductReady({ product, scope }) {
258
+ if (viewed.has(scope.root) || mainProduct() !== scope) return;
259
+ viewed.add(scope.root);
260
+ const variant = scope.variant ?? product.variants.nodes[0];
261
+ const items = [itemFromVariant(product, variant)];
262
+ const products = variant ? [productPayload(product, variant)] : [];
263
+ send("view_item", { currency: variant?.price.currencyCode, value: totalValue(items), items }, "product_viewed", {
264
+ products
265
+ });
266
+ }
267
+ function onListReady({ products, collection }) {
268
+ const items = products.slice(0, MAX_LIST_ITEMS).map((product, index) => itemFromVariant(product, product.variants.nodes[0], 1, index));
269
+ const list = { item_list_id: collection?.handle || "products", item_list_name: collection?.title || "Products" };
270
+ if (!collection) {
271
+ send("view_item_list", { ...list, items });
272
+ return;
273
+ }
274
+ send("view_item_list", { ...list, items }, "collection_viewed", {
275
+ collection: { id: collection.id, handle: collection.handle }
276
+ });
277
+ }
278
+ function sendCartChanges(cart, now, before) {
279
+ const currency = cart?.cost.totalAmount.currencyCode;
280
+ now.forEach((line, variantId) => {
281
+ const previous = before.get(variantId);
282
+ const added = line.quantity - (previous?.quantity ?? 0);
283
+ if (added <= 0) return;
284
+ const items = [itemFromLine(line, added)];
285
+ send("add_to_cart", { currency, value: totalValue(items), items }, "product_added_to_cart", {
286
+ cart,
287
+ prevCart: lastCart,
288
+ currentLine: linePayload(line),
289
+ prevLine: previous ? linePayload(previous) : void 0
290
+ });
291
+ });
292
+ before.forEach((line, variantId) => {
293
+ const removed = line.quantity - (now.get(variantId)?.quantity ?? 0);
294
+ if (removed <= 0) return;
295
+ const items = [itemFromLine(line, removed)];
296
+ send("remove_from_cart", { currency, value: totalValue(items), items });
297
+ });
298
+ }
299
+ function onCartUpdated({ cart, reason }) {
300
+ const now = new Map((cart?.lines.nodes ?? []).map((line) => [line.merchandise.id, line]));
301
+ if (lastLines && reason !== "load" && reason !== "pending") sendCartChanges(cart, now, lastLines);
302
+ lastLines = now;
303
+ lastCart = cart;
304
+ }
305
+ function onCartOpened() {
306
+ const items = Cart.lines.map((line) => itemFromLine(line));
307
+ send("view_cart", { currency: Cart.state?.cost.totalAmount.currencyCode, value: totalValue(items), items });
308
+ }
309
+ function onCheckout({ cart }) {
310
+ if (!cart) return;
311
+ const items = cart.lines.nodes.map((line) => itemFromLine(line));
312
+ const coupons = cart.discountCodes.filter((discount) => discount.applicable).map((discount) => discount.code);
313
+ send("begin_checkout", {
314
+ currency: cart.cost.totalAmount.currencyCode,
315
+ value: totalValue(items),
316
+ coupon: coupons.join(",") || void 0,
317
+ items
318
+ });
319
+ }
320
+ var REPORTERS = {
321
+ "product-ready": onProductReady,
322
+ "list-ready": onListReady,
323
+ "cart-updated": onCartUpdated,
324
+ "cart-toggled": ({ open }) => {
325
+ if (open) onCartOpened();
326
+ },
327
+ checkout: onCheckout,
328
+ search: ({ term }) => {
329
+ if (term) send("search", { search_term: term }, "search_viewed", { searchTerm: term });
187
330
  }
188
331
  };
189
- var lastLines = null;
190
- var viewed = /* @__PURE__ */ new WeakSet();
191
- function handle(e) {
192
- const name = e.type.slice(cfg.prefix.length + 1);
193
- const d = e.detail || {};
194
- if (name === "product-ready") {
195
- const scope = d.scope;
196
- if (!scope || viewed.has(scope.root) || mainProduct() !== scope) return;
197
- viewed.add(scope.root);
198
- const v = scope.variant || d.product.variants.nodes[0];
199
- const items = [itemFromVariant(d.product, v)];
200
- send("view_item", { currency: v?.price?.currencyCode, value: value(items), items }, "product_viewed", { products: [productPayload(d.product, v)] });
201
- } else if (name === "list-ready") {
202
- const items = (d.products || []).slice(0, 200).map((p, i) => itemFromVariant(p, p.variants?.nodes?.[0], 1, i));
203
- const list = { item_list_id: d.collection?.handle || "products", item_list_name: d.collection?.title || "Products" };
204
- send("view_item_list", { ...list, items }, d.collection ? "collection_viewed" : null, d.collection ? { collection: { id: d.collection.id, handle: d.collection.handle } } : null);
205
- } else if (name === "cart-updated") {
206
- const cart = d.cart;
207
- const now = new Map((cart?.lines?.nodes || []).map((l) => [l.merchandise?.id, l]));
208
- if (lastLines && d.reason !== "load" && d.reason !== "pending") {
209
- const currency = cart?.cost?.totalAmount?.currencyCode;
210
- now.forEach((l, k) => {
211
- const diff = l.quantity - (lastLines.get(k)?.quantity || 0);
212
- if (diff > 0) {
213
- const items = [itemFromLine(l, diff)];
214
- send("add_to_cart", { currency, value: value(items), items }, "product_added_to_cart", {
215
- cart,
216
- prevCart: lastCart,
217
- currentLine: analyticsLine(l),
218
- prevLine: lastLines.get(k) ? analyticsLine(lastLines.get(k)) : void 0
219
- });
220
- }
221
- });
222
- lastLines.forEach((l, k) => {
223
- const diff = l.quantity - (now.get(k)?.quantity || 0);
224
- if (diff > 0) {
225
- const items = [itemFromLine(l, diff)];
226
- send("remove_from_cart", { currency, value: value(items), items });
227
- }
228
- });
229
- }
230
- lastLines = now;
231
- lastCart = cart;
232
- } else if (name === "cart-toggled" && d.open) {
233
- const items = Cart.lines.map((l) => itemFromLine(l));
234
- send("view_cart", { currency: Cart.state?.cost?.totalAmount?.currencyCode, value: value(items), items });
235
- } else if (name === "checkout") {
236
- const items = (d.cart?.lines?.nodes || []).map((l) => itemFromLine(l));
237
- const coupon = (d.cart?.discountCodes || []).filter((c) => c.applicable).map((c) => c.code).join(",") || void 0;
238
- send("begin_checkout", { currency: d.cart?.cost?.totalAmount?.currencyCode, value: value(items), coupon, items });
239
- } else if (name === "search" && d.term) {
240
- send("search", { search_term: d.term }, "search_viewed", { searchTerm: d.term });
241
- } else if (name === "page") {
332
+ function report(event, name) {
333
+ REPORTERS[name](event.detail);
334
+ }
335
+ function handle(event) {
336
+ if (event.type === "astro:page-load") {
242
337
  viewed = /* @__PURE__ */ new WeakSet();
243
- if (bus) bus.publish("page_viewed", {});
338
+ bus?.publish("page_viewed", {});
339
+ return;
244
340
  }
341
+ ANALYTICS_EVENTS.forEach((name) => {
342
+ if (isOwnEvent(event, name)) report(event, name);
343
+ });
245
344
  }
246
- var lastCart = null;
247
345
  async function startAnalytics(queue) {
248
- if (cfg.analytics.shopify) await startShopify().catch((err) => reportError(err, "shopify analytics"));
249
- if (bus) bus.publish("page_viewed", {});
346
+ if (cfg.analytics?.shopify) {
347
+ bus = await startShopifyAnalytics(() => mainProduct() != null).catch((error) => {
348
+ reportError(error, "shopify analytics");
349
+ return null;
350
+ });
351
+ }
352
+ bus?.publish("page_viewed", {});
250
353
  queue.splice(0).forEach(handle);
251
- queue.push = (e) => {
252
- handle(e);
253
- return 0;
354
+ queue.push = (...events) => {
355
+ events.forEach(handle);
356
+ return queue.length;
254
357
  };
255
358
  }
256
359
 
257
- // src/parts/analytics.js
258
- window.Tether.__parts.analytics = analytics_exports;
360
+ // src/parts/analytics.ts
361
+ var { Tether } = window;
362
+ if (!Tether) throw new Error("tether.analytics.js runs after the Tether script, which loads it");
363
+ Tether.__parts.analytics = analytics_exports;
259
364
  })();