@occluze/tether 0.6.8 → 0.7.1

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 (215) hide show
  1. package/README.md +28 -28
  2. package/dist/esm/astro.js +2 -2
  3. package/dist/esm/chunks/account-CXMA5RPZ.js +1 -0
  4. package/dist/esm/chunks/account-pages-IZO7FEOZ.js +1 -0
  5. package/dist/esm/chunks/analytics-PG5FPRDN.js +1 -0
  6. package/dist/esm/chunks/chunk-4HD4J5JC.js +1 -0
  7. package/dist/esm/chunks/chunk-6TFMLT4A.js +4 -0
  8. package/dist/esm/chunks/chunk-BBVUVPMO.js +1 -0
  9. package/dist/esm/chunks/chunk-E5YO6274.js +1 -0
  10. package/dist/esm/chunks/chunk-EW5SYO6L.js +1 -0
  11. package/dist/esm/chunks/chunk-HJY2JSNB.js +1 -0
  12. package/dist/esm/chunks/chunk-MQYB6BH4.js +1 -0
  13. package/dist/esm/chunks/chunk-N3V45JPS.js +1 -0
  14. package/dist/esm/chunks/chunk-RPMBCAGS.js +1 -0
  15. package/dist/esm/chunks/chunk-VFNHIGCS.js +1 -0
  16. package/dist/esm/chunks/chunk-WT7RGGJU.js +1 -0
  17. package/dist/esm/chunks/chunk-YN6LEBEN.js +1 -0
  18. package/dist/esm/chunks/chunk-Z6HS3H7K.js +1 -0
  19. package/dist/esm/chunks/diagnose-XCEBQKBO.js +14 -0
  20. package/dist/esm/chunks/extras-4HU3VSBQ.js +1 -0
  21. package/dist/esm/chunks/markets-ui-M4IQ62CT.js +1 -0
  22. package/dist/esm/chunks/search-A5DS2IOS.js +1 -0
  23. package/dist/esm/index.js +1 -1
  24. package/dist/esm/server.js +2 -2
  25. package/dist/presets/barba.esm.js +19 -23
  26. package/dist/tether.account-pages.js +332 -367
  27. package/dist/tether.account-pages.min.js +1 -1
  28. package/dist/tether.account.js +253 -492
  29. package/dist/tether.account.min.js +1 -1
  30. package/dist/tether.analytics.js +82 -89
  31. package/dist/tether.analytics.min.js +1 -1
  32. package/dist/tether.diagnose.js +52 -34
  33. package/dist/tether.diagnose.min.js +2 -2
  34. package/dist/tether.extras.js +42 -37
  35. package/dist/tether.extras.min.js +1 -1
  36. package/dist/tether.js +1361 -935
  37. package/dist/tether.markets.js +89 -91
  38. package/dist/tether.markets.min.js +1 -1
  39. package/dist/tether.min.js +0 -0
  40. package/dist/tether.min.js.map +4 -4
  41. package/dist/tether.search.js +60 -69
  42. package/dist/tether.search.min.js +1 -1
  43. package/dist/types/server/src/shared/account-orders.d.ts +44 -0
  44. package/dist/types/server/src/shared/account-routes.d.ts +153 -0
  45. package/dist/types/server/src/shared/api-versions.d.ts +13 -0
  46. package/dist/types/server/src/shared/cart-id.d.ts +2 -0
  47. package/dist/types/server/src/shared/error-message.d.ts +2 -0
  48. package/dist/types/server/src/shared/json.d.ts +25 -0
  49. package/dist/types/server/src/shared/market-codes.d.ts +16 -0
  50. package/dist/types/src/account/addresses-view.d.ts +5 -0
  51. package/dist/types/src/account/answers.d.ts +40 -0
  52. package/dist/types/src/account/markup.d.ts +19 -0
  53. package/dist/types/src/account/operations.d.ts +41 -0
  54. package/dist/types/src/account/order-lines.d.ts +13 -0
  55. package/dist/types/src/account/order-list.d.ts +12 -0
  56. package/dist/types/src/account/order-page.d.ts +6 -0
  57. package/dist/types/src/account/page-answers.d.ts +182 -0
  58. package/dist/types/src/account/page-events.d.ts +2 -0
  59. package/dist/types/src/account/server-client.d.ts +60 -0
  60. package/dist/types/src/account/subscriptions-view.d.ts +2 -0
  61. package/dist/types/src/account-api.d.ts +18 -0
  62. package/dist/types/src/account-marks.d.ts +15 -0
  63. package/dist/types/src/account-pages.d.ts +8 -0
  64. package/dist/types/src/account.d.ts +64 -0
  65. package/dist/types/src/amounts.d.ts +12 -0
  66. package/dist/types/src/analytics-shopify.d.ts +41 -0
  67. package/dist/types/src/analytics.d.ts +2 -0
  68. package/dist/types/src/api-version.d.ts +28 -0
  69. package/dist/types/src/astro.d.ts +42 -0
  70. package/dist/types/src/cart/cart-shape.d.ts +43 -0
  71. package/dist/types/src/cart/checkout.d.ts +16 -0
  72. package/dist/types/src/cart/drawer.d.ts +18 -0
  73. package/dist/types/src/cart/mutations.d.ts +85 -0
  74. package/dist/types/src/cart/render.d.ts +17 -0
  75. package/dist/types/src/cart/store.d.ts +185 -0
  76. package/dist/types/src/cart.d.ts +106 -0
  77. package/dist/types/src/client.d.ts +134 -0
  78. package/dist/types/src/collection.d.ts +25 -0
  79. package/dist/types/src/config-sections.d.ts +40 -0
  80. package/dist/types/src/config.d.ts +190 -0
  81. package/dist/types/src/controls/cart-controls.d.ts +2 -0
  82. package/dist/types/src/controls/discount.d.ts +2 -0
  83. package/dist/types/src/controls/extras.d.ts +5 -0
  84. package/dist/types/src/controls/navigation.d.ts +12 -0
  85. package/dist/types/src/diagnose-markup.d.ts +19 -0
  86. package/dist/types/src/diagnose.d.ts +60 -0
  87. package/dist/types/src/dom.d.ts +75 -0
  88. package/dist/types/src/extras.d.ts +21 -0
  89. package/dist/types/src/fragments.d.ts +158 -0
  90. package/dist/types/src/globals.d.ts +15 -0
  91. package/dist/types/src/images.d.ts +20 -0
  92. package/dist/types/src/index.d.ts +167 -0
  93. package/dist/types/src/initial.d.ts +56 -0
  94. package/dist/types/src/lazy.d.ts +28 -0
  95. package/dist/types/src/loader.d.ts +84 -0
  96. package/dist/types/src/market-codes.d.ts +6 -0
  97. package/dist/types/src/markets-ui.d.ts +32 -0
  98. package/dist/types/src/markets.d.ts +72 -0
  99. package/dist/types/src/markup.d.ts +131 -0
  100. package/dist/types/src/mounting.d.ts +46 -0
  101. package/dist/types/src/page-market.d.ts +27 -0
  102. package/dist/types/src/presets/barba.d.ts +56 -0
  103. package/dist/types/src/product-events.d.ts +2 -0
  104. package/dist/types/src/product-render.d.ts +17 -0
  105. package/dist/types/src/product-shape.d.ts +90 -0
  106. package/dist/types/src/product-state.d.ts +110 -0
  107. package/dist/types/src/product.d.ts +66 -0
  108. package/dist/types/src/repeaters.d.ts +16 -0
  109. package/dist/types/src/search.d.ts +33 -0
  110. package/dist/types/src/selling-plans.d.ts +64 -0
  111. package/dist/types/src/server.d.ts +88 -0
  112. package/dist/types/src/shopify-values.d.ts +46 -0
  113. package/dist/types/src/status.d.ts +33 -0
  114. package/dist/types/src/storage.d.ts +12 -0
  115. package/dist/types/src/store-html.d.ts +39 -0
  116. package/dist/types/src/storefront/catalog.d.ts +38 -0
  117. package/dist/types/src/storefront/json-ld.d.ts +20 -0
  118. package/dist/types/src/variant-render.d.ts +14 -0
  119. package/package.json +24 -24
  120. package/dist/esm/chunks/account-C3NP6HFB.js +0 -1
  121. package/dist/esm/chunks/account-pages-WLK374FO.js +0 -1
  122. package/dist/esm/chunks/analytics-G3SAWMNL.js +0 -1
  123. package/dist/esm/chunks/chunk-27PJJZGC.js +0 -1
  124. package/dist/esm/chunks/chunk-2FSXS55U.js +0 -1
  125. package/dist/esm/chunks/chunk-FCSWQDVV.js +0 -1
  126. package/dist/esm/chunks/chunk-FOMSMIAM.js +0 -1
  127. package/dist/esm/chunks/chunk-GZJTCLLW.js +0 -1
  128. package/dist/esm/chunks/chunk-HEQILZVR.js +0 -1
  129. package/dist/esm/chunks/chunk-JOOEXYF3.js +0 -4
  130. package/dist/esm/chunks/chunk-MPTQYLSM.js +0 -1
  131. package/dist/esm/chunks/chunk-NEHZ37TU.js +0 -3
  132. package/dist/esm/chunks/chunk-V74KGEJF.js +0 -1
  133. package/dist/esm/chunks/chunk-VT4CDUJJ.js +0 -1
  134. package/dist/esm/chunks/chunk-YJLWX2HK.js +0 -1
  135. package/dist/esm/chunks/diagnose-6VVGZNTY.js +0 -14
  136. package/dist/esm/chunks/extras-GJVRDFM3.js +0 -1
  137. package/dist/esm/chunks/markets-ui-UNB4PTA7.js +0 -1
  138. package/dist/esm/chunks/search-OU75RNQL.js +0 -1
  139. package/src/account/addresses-view.js +0 -92
  140. package/src/account/browser-session.js +0 -359
  141. package/src/account/markup.js +0 -48
  142. package/src/account/operations.js +0 -180
  143. package/src/account/order-lines.js +0 -96
  144. package/src/account/order-list.js +0 -91
  145. package/src/account/order-page.js +0 -192
  146. package/src/account/page-events.js +0 -288
  147. package/src/account/server-client.js +0 -172
  148. package/src/account/shared.js +0 -111
  149. package/src/account/shopify-auth.js +0 -150
  150. package/src/account/subscriptions-view.js +0 -158
  151. package/src/account-api.js +0 -118
  152. package/src/account-links.js +0 -35
  153. package/src/account-pages.js +0 -89
  154. package/src/account.js +0 -342
  155. package/src/amounts.js +0 -36
  156. package/src/analytics-shopify.js +0 -241
  157. package/src/analytics.js +0 -352
  158. package/src/api-version.js +0 -85
  159. package/src/astro.js +0 -266
  160. package/src/cart/checkout.js +0 -97
  161. package/src/cart/drawer.js +0 -138
  162. package/src/cart/mutations.js +0 -234
  163. package/src/cart/render.js +0 -294
  164. package/src/cart/store.js +0 -326
  165. package/src/cart.js +0 -391
  166. package/src/client.js +0 -267
  167. package/src/collection.js +0 -183
  168. package/src/config.js +0 -349
  169. package/src/controls/cart-controls.js +0 -155
  170. package/src/controls/discount.js +0 -96
  171. package/src/controls/extras.js +0 -63
  172. package/src/controls/navigation.js +0 -83
  173. package/src/diagnose-markup.js +0 -333
  174. package/src/diagnose.js +0 -295
  175. package/src/dom.js +0 -287
  176. package/src/extras.js +0 -145
  177. package/src/fragments.js +0 -237
  178. package/src/images.js +0 -104
  179. package/src/index.js +0 -353
  180. package/src/initial.js +0 -87
  181. package/src/lazy-iife.js +0 -116
  182. package/src/lazy.js +0 -39
  183. package/src/loader.js +0 -337
  184. package/src/market-codes.js +0 -35
  185. package/src/markets-ui.js +0 -204
  186. package/src/markets.js +0 -334
  187. package/src/markup.js +0 -64
  188. package/src/mounting.js +0 -277
  189. package/src/page-market.js +0 -116
  190. package/src/parts/account-pages.js +0 -6
  191. package/src/parts/account.js +0 -6
  192. package/src/parts/analytics.js +0 -6
  193. package/src/parts/diagnose.js +0 -6
  194. package/src/parts/extras.js +0 -6
  195. package/src/parts/markets.js +0 -6
  196. package/src/parts/search.js +0 -6
  197. package/src/presets/barba.js +0 -190
  198. package/src/product-events.js +0 -130
  199. package/src/product-render.js +0 -257
  200. package/src/product-state.js +0 -318
  201. package/src/product.js +0 -344
  202. package/src/repeaters.js +0 -173
  203. package/src/search.js +0 -323
  204. package/src/selling-plans.js +0 -154
  205. package/src/server.js +0 -215
  206. package/src/shopify-values.js +0 -89
  207. package/src/status.js +0 -126
  208. package/src/store-html.js +0 -0
  209. package/src/storefront/catalog.js +0 -199
  210. package/src/storefront/json-ld.js +0 -167
  211. package/src/variant-render.js +0 -165
  212. package/types/astro.d.ts +0 -28
  213. package/types/barba.d.ts +0 -16
  214. package/types/index.d.ts +0 -577
  215. package/types/server.d.ts +0 -182
@@ -1 +1 @@
1
- "use strict";(()=>{var Gt=Object.defineProperty;var Ht=(t,e)=>{for(var r in e)Gt(t,r,{get:e[r],enumerable:!0})};var at={};Ht(at,{addresses:()=>ke,customer:()=>st,deleteAddress:()=>Se,getToken:()=>L,handleCallback:()=>ot,isLoggedIn:()=>jt,login:()=>qt,logout:()=>Jt,mountAccount:()=>Le,order:()=>xe,orders:()=>Bt,query:()=>Mt,render:()=>it,requestReturn:()=>Ce,saveAddress:()=>Ee,subscriptionAction:()=>Ae,subscriptions:()=>_e,updateProfile:()=>Te});var zt=window.Tether.__core["config.js"],{DEFAULTS:Ne,cfg:i,configure:Re,isConfigured:Pe,log:ct,reportError:w,resolveConfig:De,toMetafieldIdentifier:$e,warn:ve}=zt;var Vt=window.Tether.__core["client.js"],{TetherError:m,endpoint:qe,gql:Me,request:Be,unwrap:Je,withContext:Ke}=Vt;var Qt=window.Tether.__core["dom.js"],{attr:Ge,busy:He,cdnUrl:ze,emit:E,formatDate:Ve,formatMoney:R,formatPercent:Qe,get:h,has:Ye,hasTemplate:We,imageUrl:Xe,notifyLayoutChanged:Ze,parseJSONAttr:tr,productUrl:er,qsa:p,repeat:j,repeatKeyed:rr,sameImage:or,scoped:nr,sel:u,setImage:q,setSelected:sr,setStoreHtml:ir,setText:C,setTextTracked:ar,show:P,toAttributes:cr,watchImages:ur}=Qt;var Yt=window.Tether.__core["cart.js"],{Cart:g,trapFocus:dr}=Yt;var Wt=window.Tether.__core["lazy.js"],{coreModules:mr,loadPart:ut}=Wt;var Xt="amount currencyCode",lt="query TetherCustomer { customer { id firstName lastName displayName emailAddress { emailAddress } defaultAddress { formatted } } }",dt=`query TetherOrders($first:Int!){customer{orders(first:$first,sortKey:PROCESSED_AT,reverse:true){nodes{id name processedAt financialStatus fulfillmentStatus statusPageUrl totalPrice{${Xt}}lineItems(first:20){nodes{title variantTitle quantity image{url altText}}}}}}}`;function Q(t){return btoa(String.fromCharCode(...new Uint8Array(t))).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function ft(t){let e=t.replace(/-/g,"+").replace(/_/g,"/").padEnd(Math.ceil(t.length/4)*4,"=");return Uint8Array.from(atob(e),r=>r.charCodeAt(0))}function M(t=32){return Q(crypto.getRandomValues(new Uint8Array(t)))}var B=()=>`${i.prefix}:account:${i.domain}`,J=()=>`${i.prefix}:account-login:${i.domain}`,Zt=()=>`${i.prefix}:account-hint:${i.domain}`,K=()=>i.account?.remember?"local":"session",Y=t=>t==="local"?window.localStorage:window.sessionStorage;function W(t,e){try{return JSON.parse(Y(t).getItem(e)??"null")}catch{return null}}function S(t,e,r){try{r===null?Y(t).removeItem(e):Y(t).setItem(e,JSON.stringify(r))}catch{}}function X(t){S("local",Zt(),t?1:null)}var x=t=>typeof t=="object"&&t!==null&&!Array.isArray(t),l=t=>typeof t=="string"?t:null;async function b(t){let e;try{e=await t.json()}catch{return{}}return x(e)?e:{}}function _(t){let e=i.account?.navigate;e?e(t):window.location.assign(t)}var F=t=>t||i.account?.locale||(i.locale||"").split("-")[0]||"",G=()=>i.country?i.country.toUpperCase():"";var te=3600,H=null;async function mt(t){let e=i.account?.shopDomain||i.domain,r=await fetch(`https://${e}/.well-known/${t}`);if(!r.ok)throw new m(`Customer accounts: ${t} answered ${r.status}`,{status:r.status});let o=await r.json();return x(o)?o:{}}function D(t,e){let r=l(t[e]);if(!r)throw new m(`Customer accounts: Shopify named no ${e}`);return r}async function I(){if(H)return H;let[t,e]=await Promise.all([mt("openid-configuration"),mt("customer-account-api")]);return H={issuer:D(t,"issuer"),authorizationEndpoint:D(t,"authorization_endpoint"),tokenEndpoint:D(t,"token_endpoint"),endSessionEndpoint:D(t,"end_session_endpoint"),graphql:D(e,"graphql_api")},H}async function Z(t){let{tokenEndpoint:e}=await I(),r=await fetch(i.account?.tokenUrl||e,{method:"POST",body:new URLSearchParams(t)}),o=await b(r),n=l(o.access_token);if(!r.ok||!n){let s=r.status===400||r.status===401;throw new m(`Customer accounts: token ${r.status} ${l(o.error)??""}`.trim(),{status:r.status,code:s?"SESSION_ENDED":"TOKEN_FAILED"})}return{access:n,refresh:l(o.refresh_token)||null,idToken:l(o.id_token)||null,expiresInSeconds:Number(o.expires_in)||te}}function ee(t){let e=t.split(".")[1];if(!e)return null;let r;try{r=JSON.parse(new TextDecoder().decode(ft(e)))}catch{return null}return x(r)?r:null}function pt(t,{nonce:e,issuer:r,client:o}){let n=t?ee(t):null;if(!n)return!1;let s=n.aud,a=Array.isArray(s)?s:[s],c=n.exp;return n.nonce===e&&n.iss===r&&a.includes(o)&&typeof c=="number"&&c*1e3>=Date.now()}var re=120,oe=600*1e3,d=null,O=null,tt=null;function ne(t){if(!x(t))return null;let e=t.access,r=t.expiresAt;return typeof e!="string"||typeof r!="number"?null:{access:e,expiresAt:r,refresh:l(t.refresh),idToken:l(t.idToken)}}function se(t){if(!x(t))return null;let{state:e,nonce:r,verifier:o,redirect:n,returnTo:s,at:a}=t;return typeof e!="string"||typeof r!="string"||typeof o!="string"||typeof n!="string"||typeof s!="string"||typeof a!="number"?null:{state:e,nonce:r,verifier:o,redirect:n,returnTo:s,at:a}}var gt=()=>d??ne(W(K(),B())),wt=()=>d?.access??null,et=()=>!!(d&&(d.refresh||d.access&&d.expiresAt>Date.now()));function rt(){let t=i.account?.clientId;if(!t)throw new m("Customer accounts: set account.clientId",{code:"NOT_CONFIGURED"});return t}var ie=async t=>Q(await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t)));async function ht({returnTo:t,locale:e}){let r=rt(),o=await I(),n={state:M(),nonce:M(),verifier:M(),redirect:i.account?.callbackUrl||`${window.location.origin}${window.location.pathname}`,returnTo:t,at:Date.now()};S("session",J(),n);let s=new URL(o.authorizationEndpoint),a={client_id:r,scope:"openid email customer-account-api:full",response_type:"code",redirect_uri:n.redirect,state:n.state,nonce:n.nonce,code_challenge:await ie(n.verifier),code_challenge_method:"S256"},c=F(e);c&&(a.locale=c);let f=G();f&&(a.region_country=f),Object.entries(a).forEach(([k,v])=>{s.searchParams.set(k,v)}),_(s.toString())}function yt(t,e){d={access:t.access,expiresAt:Date.now()+Math.max(0,t.expiresInSeconds-re)*1e3,refresh:t.refresh??e?.refresh??null,idToken:t.idToken??e?.idToken??null},S(K(),B(),d)}async function ot(){let t=new URLSearchParams(window.location.search),e=se(W("session",J()));if(!e||!t.has("code")&&!t.has("error")||t.get("state")!==e.state)return!1;S("session",J(),null);let r=new URL(window.location.href);["code","state","iss","error","error_description"].forEach(f=>{r.searchParams.delete(f)}),window.history.replaceState(window.history.state,"",r);let o=t.get("error");if(o!==null)return E("account-error",{error:o}),!1;if(Date.now()-e.at>oe)throw new m("Customer accounts: the login took too long, please try again");let n=rt(),s=await Z({grant_type:"authorization_code",client_id:n,redirect_uri:e.redirect,code:t.get("code")??"",code_verifier:e.verifier}),{issuer:a}=await I();if(!pt(s.idToken,{nonce:e.nonce,issuer:a,client:n}))throw new m("Customer accounts: the login answer did not check out (nonce/issuer/audience)");yt(s,null),await xt(),E("account-login",{});let c=e.returnTo?new URL(e.returnTo,window.location.href):null;return c?.origin===window.location.origin&&c.href!==r.href&&_(c.href),!0}function nt(){d=null,O=null,S(K(),B(),null),g.setCustomer({accessToken:null})}async function ae(t){try{let e=await Z({grant_type:"refresh_token",client_id:rt(),refresh_token:t.refresh??""});yt(e,t),await xt()}catch(e){if(e instanceof m&&e.code==="SESSION_ENDED")nt();else throw e}}async function L(){return d=gt(),d?d.access&&d.expiresAt>Date.now()?d.access:d.refresh?(tt??(tt=ae(d).finally(()=>{tt=null})),await tt,wt()):(nt(),null):null}async function xt(){let t=wt();if(g.setCustomer({accessToken:t}),!(!g.id()||!t))try{await g.setBuyerIdentity({customerAccessToken:t},{create:!1})}catch(e){w(e,"account cart")}}async function ce(){if(g.id())try{await g.setBuyerIdentity({customerAccessToken:null},{create:!1})}catch(t){w(t,"account cart unlink"),S("local",i.storageKey,null)}}async function Tt(t){let e=gt()?.idToken??null;if(await ce(),nt(),E("account-logout",{}),!e)return"stayed";let r=new URL((await I()).endSessionEndpoint);return r.searchParams.set("id_token_hint",e),r.searchParams.set("post_logout_redirect_uri",t),_(r.toString()),"redirected"}async function z(t,e={}){let r=await L();if(!r)throw new m("Not logged in",{code:"NOT_LOGGED_IN"});let{graphql:o}=await I(),n=f=>fetch(o,{method:"POST",headers:{"Content-Type":"application/json",Authorization:f},body:JSON.stringify({query:t,variables:e})}),s=await n(r);s.status===401&&d?.refresh&&(d.expiresAt=0,s=await n(await L()??""));let a=await b(s),c=Array.isArray(a.errors)?a.errors:[];if(!s.ok||c.length){let f=c.map(k=>x(k)?l(k.message):null).filter(Boolean);throw new m(f.join(" | ")||`Customer accounts: ${s.status}`,{status:s.status})}return a.data}async function kt(){return O||(O=(await z(lt)).customer,O)}function Et(){O=null}var A=null;function y(){let t=i.account?.server;return t?new URL(t,window.location.href).href.replace(/\/$/,""):""}async function U(t,{method:e="GET",body:r}={}){let o={method:e,credentials:"include"};e==="POST"&&(o.headers={"Content-Type":"application/json","X-Tether-Account":"1"}),r&&(o.body=JSON.stringify(r));let n=await fetch(`${y()}${t}`,o);if(n.status===401)return{kind:"logged-out"};let s=await b(n);if(!n.ok){let a=l(s.error)??String(n.status),c=Array.isArray(s.userErrors)?s.userErrors:void 0;throw new m(`Customer accounts: ${a}`,{status:n.status,...c&&{userErrors:c}})}return{kind:"answer",data:s}}function ue(t){let e=x(t)?t:{},r=e.address;return{firstName:l(e.firstName),lastName:l(e.lastName),displayName:l(e.displayName),email:l(e.email),address:Array.isArray(r)?r.filter(o=>typeof o=="string"):null}}async function V(){if(!A){let t=await U("/me");A=t.kind==="answer"&&t.data.loggedIn===!0?{loggedIn:!0,customer:ue(t.data.customer)}:{loggedIn:!1}}return X(A.loggedIn),A}var St=()=>A?.loggedIn===!0;function _t(){A=null}function At({returnTo:t,locale:e}){let r=new URL(`${y()}/login`);r.searchParams.set("returnTo",t);let o=F(e);o&&r.searchParams.set("locale",o);let n=G();n&&r.searchParams.set("country",n),_(r.toString())}async function Ct(){let t=g.id();if(!(await V()).loggedIn||!t)return null;let e=await U("/cart",{method:"POST",body:{cartId:t}});if(e.kind==="logged-out")return null;let r=l(e.data.checkoutUrl);return r?`${r}${r.includes("?")?"&":"?"}logged_in=true`:null}async function bt(t){let e=await U("/logout",{method:"POST",body:{returnTo:t,cartId:g.id()}});A=null,X(!1),E("account-logout",{});let r=e.kind==="answer"?l(e.data.logoutUrl):null;return r?(_(r),"redirected"):"stayed"}var le=window.Tether.__core["shopify-values.js"],{STORE_ENV_NAMES:qr,formatMoney:Mr,isHttpsUrl:It,isSecretShopifyToken:Br,productKey:Jr,productUrl:Kr}=le;function Ot(t){try{return new Date(t).toLocaleDateString(i.locale)}catch(e){if(e instanceof RangeError)return t;throw e}}function Lt(t){let e=i.account?.orderUrl;if(e){let r=t.id.split("/").pop()?.split("?")[0]??"";return e.replace("{id}",encodeURIComponent(r))}return It(t.statusPageUrl)?t.statusPageUrl??null:null}function $(t,e,r){p(t,u(e)).forEach(o=>{let n=h(o,e)??"";Object.hasOwn(r,n)&&P(o,r[n]===!0)})}var Ut=(t,e)=>p(t,u(e)).concat(t.matches(u(e))?[t]:[]);var N=(t,e)=>Object.hasOwn(t,e)?t[e]:void 0;var de=(t,e)=>({title:t.title||t.name,"variant-title":t.variantTitle||"",quantity:String(t.quantity),price:R(t.price),total:R(t.totalPrice),sku:t.sku||"",returnable:e===null?void 0:String(e)}),fe=t=>t.tagName==="INPUT";function me(t,e,r){$(t,"order-line-show",{returnable:r>0}),p(t,u("return-quantity")).forEach(o=>{fe(o)&&(o.max=String(r),o.min="0",o.value||(o.value="0"),o.disabled=r<1)}),p(t,`select${u("return-reason")}`).forEach(o=>{o.dataset.tetherFilled!==e.id&&(o.dataset.tetherFilled=e.id,(e.suggestedReturnReasonDefinitions?.nodes??[]).forEach(n=>{o.appendChild(new Option(n.name,n.id))}))})}function Nt(t,e,r){j(t,e,(o,n)=>{let s=n.id,a=r&&s?r.get(s)??0:null;s&&(o.dataset.tetherLine=s);let c=de(n,a);Ut(o,"order-line").forEach(f=>{let k=h(f,"order-line")??"";if(k==="image"){n.image&&q(f,n.image.url,n.image.altText||n.title);return}let v=N(c,k);v!==void 0&&C(f,v)}),s&&a!==null&&me(o,{...n,id:s},a)})}var Rt=10,pe=t=>({name:t.name,date:Ot(t.processedAt),total:R(t.totalPrice),status:t.financialStatus?.toLowerCase(),fulfillment:t.fulfillmentStatus?.toLowerCase(),items:t.lineItems.nodes.map(e=>`${e.quantity}\xD7 ${e.title}`).join(", ")});function ge(t,e){let r=e.lineItems.nodes,o=Lt(e),n=pe(e);p(t,u("order-bind")).forEach(s=>{let a=h(s,"order-bind")??"";if(a==="url"){o&&s.setAttribute("href",o);return}if(a==="image"){let f=r.find(k=>k.image)?.image;f&&q(s,f.url,f.altText||r[0]?.title||"");return}let c=N(n,a);c!==void 0&&C(s,c)}),p(t,u("order-lines")).forEach(s=>{Nt(s,r,null)}),h(t,"order-bind")==="url"&&o&&t.setAttribute("href",o)}async function Pt(t,e){let r=p(t,u("orders")),o=r[0];if(!o)return;$(t,"show",{"orders-loading":!0,"orders-empty":!1});let n=Number.parseInt(h(o,"limit")||String(Rt),10)||Rt,s=await e(n).catch(a=>(w(a,"orders"),null));$(t,"show",{"orders-loading":!1,"orders-empty":s?.length===0}),r.forEach(a=>{j(a,s??[],ge)})}var we=["order","addresses","subscriptions","profile-form","address-form"];function jt(){return y()?St():et()}async function qt({returnTo:t=window.location.href,locale:e}={}){y()?At({returnTo:t,locale:e}):await ht({returnTo:t,locale:e})}async function Mt(t,e={}){if(y())throw new m("Customer accounts in server mode only answer customer() and orders()",{code:"NOT_ALLOWED"});return z(t,e)}async function st(){if(!y())return kt();let t=await V();return t.loggedIn?{...t.customer,emailAddress:{emailAddress:t.customer.email},defaultAddress:{formatted:t.customer.address}}:null}async function Bt({first:t=10}={}){if(y()){let r=await U(`/orders?first=${t}`);if(r.kind==="logged-out")return[];let o=r.data.orders;return Array.isArray(o)?o:[]}return(await z(dt,{first:t})).customer?.orders.nodes??[]}async function Jt({returnTo:t=i.account?.logoutUrl||`${window.location.origin}/`}={}){(y()?await bt(t):await Tt(t))==="stayed"&&await it(document)}async function he(){try{return y()?(await V()).loggedIn?{kind:"logged-in"}:{kind:"logged-out"}:et()||await L()?{kind:"logged-in"}:{kind:"logged-out"}}catch(t){return{kind:"unknown",error:t}}}var Dt=t=>we.some(e=>p(t,u(e)).length>0);function ye(t){let e=i.account;p(t,u("account-link")).forEach(r=>{let o=h(r,"account-link"),n=e?.subscriptionsUrl,s=o==="payment"&&(e?.paymentUrl||n)||o==="subscriptions"&&n;r.setAttribute("href",s||`https://${i.domain}/account`)})}async function it(t=document){let e=await he();e.kind==="unknown"&&w(e.error,"account");let r=e.kind==="logged-in";if(p(t,u("show")).forEach(o=>{let n=h(o,"show");n==="logged-in"&&P(o,r),n==="logged-out"&&P(o,!r)}),ye(t),e.kind==="unknown"&&Dt(t)){(await T()).showUnavailable(t);return}r&&(await Kt(t),await Promise.all([Pt(t,o=>Bt({first:o})),Dt(t)?T().then(o=>o.renderPages(t)):null]))}async function Kt(t){let e=p(t,u("account-bind"));if(!e.length)return;let r=await st().catch(n=>(w(n,"account"),null)),o={"first-name":r?.firstName,"last-name":r?.lastName,name:r?.displayName,email:r?.emailAddress?.emailAddress,address:r?.defaultAddress?.formatted?.join(", ")};e.forEach(n=>{let s=N(o,h(n,"account-bind")??"");s!=null&&C(n,s)})}var $t=null;function T(){return $t??($t=ut("account-pages").then(t=>(t.setup({serverBase:y,serverFetch:U,query:Mt,customer:st,bindCustomer:Kt,reset:()=>{Et(),_t()}}),t))),$t}var xe=t=>T().then(e=>e.order(t)),Te=t=>T().then(e=>e.updateProfile(t)),ke=()=>T().then(t=>t.addresses()),Ee=(t,e)=>T().then(r=>r.saveAddress(t,e)),Se=t=>T().then(e=>e.deleteAddress(t)),_e=()=>T().then(t=>t.subscriptions()),Ae=(t,e)=>T().then(r=>r.subscriptionAction(t,e)),Ce=(t,e)=>T().then(r=>r.requestReturn(t,e));function be(t){let e=t.target;e instanceof window.Element&&(e.closest(u("account-login"))?(t.preventDefault(),qt().catch(r=>{w(r,"login")})):e.closest(u("account-logout"))&&(t.preventDefault(),Jt().catch(r=>{w(r,"logout")})))}function Ie(){let t=new URL(window.location.href);t.searchParams.get("account")&&(t.searchParams.delete("account"),window.history.replaceState(window.history.state,"",t),E("account-login",{})),g.setCustomer({beforeCheckout:Ct})}async function Oe(){try{await ot()}catch(t){w(t,"login")}if(!g.customerAccessToken)try{let t=await L();t&&g.setCustomer({accessToken:t})}catch(t){w(t,"account")}}var vt=!1;async function Le(t=document){vt||(vt=!0,document.addEventListener("click",be),y()?Ie():await Oe(),ct("account",jt()?"logged in":"logged out")),await it(t)}var{Tether:Ft}=window;if(!Ft)throw new Error("tether.account.js runs after the Tether script, which loads it");Ft.__parts.account=at;})();
1
+ (()=>{var Pt=Object.defineProperty;var Tt=(t,e)=>{for(var r in e)Pt(t,r,{get:e[r],enumerable:!0})};var j={};Tt(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,me,V,fe,ge,y,pe]=St;var Lt=window.Tether.__core["client.ts"],[he,ye,xe,Ae,p]=Lt;var bt=window.Tether.__core["dom.ts"],[ke,Pe,Te,P,B,T,m,Se,Le,be,Re,Ee,d,E,c,I,A,S]=bt;var Rt=window.Tether.__core["cart.ts"],[L]=Rt;var Et=window.Tether.__core["lazy.ts"],[G]=Et;function g(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function a(t,e){return g(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)}),$=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 D(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 p(`Customer accounts: the answer has no ${t}`);function Y(t){let e=g(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:$(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)?$(r):null,code:i(a(t,"code"))}}var tt=t=>N(t,Mt).filter(e=>e!==null);var x=null;function et(){let t=u.account?.server;if(!t)throw new p("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"):D(q())}async function $t(t,e){try{return await fetch(t,e)}catch(r){throw new p(`Network error: ${z(r)}`,{code:"NETWORK"})}}async function Dt(t){let e;try{e=await t.json()}catch{return{}}return g(e)?e:{}}async function O(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 $t(`${et()}${t}`,n);if(o.status===401)return{kind:"logged-out"};let s=await Dt(o);if(!o.ok){let l=i(s.error)??String(o.status),w=tt(s.userErrors);throw new p(`Customer accounts: ${l}`,{status:o.status,...w.length>0&&{userErrors:w},...s.code==="INVALID"&&{code:"INVALID"}})}return{kind:"answer",data:s}}async function v(){if(!x){let t=await O("/me");x=t.kind==="answer"&&t.data.loggedIn===!0?{loggedIn:!0,customer:Y(t.data.customer)}:{loggedIn:!1}}return rt(x.loggedIn),x}var nt=()=>x?.loggedIn===!0;function ot(){x=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=L.id();if(!(await v()).loggedIn||!t)return null;let e=await O("/cart",{method:"POST",body:{cartId:t}});return e.kind==="logged-out"?null:i(e.data.checkoutUrl)}async function ct(t){let e=await O("/logout",{method:"POST",body:{returnTo:t,cartId:L.id()}});x=null,rt(!1),P("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){d(t,c(e)).forEach(n=>{let o=m(n,e)??"";Object.hasOwn(r,o)&&S(n,r[o]===!0)})}var dt=(t,e)=>d(t,c(e)).concat(t.matches(c(e))?[t]:[]);var k=(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}),d(t,c("return-quantity")).forEach(n=>{Ht(n)&&(n.max=String(r),n.min="0",n.value||(n.value="0"),n.disabled=r<1)}),d(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 lt(t,e,r){E(t,e,(n,o)=>{let s=o.id,l=r&&s?r.get(s)??0:null;s&&(n.dataset.tetherLine=s);let w=jt(o,l);dt(n,"order-line").forEach(h=>{let R=m(h,"order-line")??"";if(R==="image"){o.image&&I(h,o.image.url,o.image.altText||o.title||"");return}let H=k(w,R);H!==void 0&&A(h,H)}),s&&l!==null&&Vt(n,{...o,id:s},l)})}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);d(t,c("order-bind")).forEach(s=>{let l=m(s,"order-bind")??"";if(l==="url"){n&&s.setAttribute("href",n);return}if(l==="image"){let h=r.find(R=>R.image)?.image;h&&I(s,h.url,h.altText||r[0]?.title||"");return}let w=k(o,l);w!==void 0&&A(s,w)}),d(t,c("order-lines")).forEach(s=>{lt(s,r,null)}),m(t,"order-bind")==="url"&&n&&t.setAttribute("href",n)}async function ft(t,e){let r=d(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(l){y(l,"orders"),s=null}b(t,"show",{"orders-loading":!1,"orders-empty":s?.length===0}),r.forEach(l=>{E(l,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 p(`Customer accounts: orders() takes first from 1 to ${String(U)}`,{code:"INVALID"});let e=await O(`/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=>d(t,c(e)).length>0);function Zt(t){d(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"&&y(e.error,"account");let r=e.kind==="logged-in";if(d(t,c("show")).forEach(n=>{let o=m(n,"show");o==="logged-in"&&S(n,r),o==="logged-out"&&S(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=d(t,c("account-bind"));if(!e.length)return;let r;try{r=await F()}catch(o){y(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=k(n,m(o,"account-bind")??"");s!=null&&A(o,s)})}var pt=null;function f(){return pt??(pt=G("account-pages").then(t=>(t.setup({serverFetch:O,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=>{y(r,"login")})):e.closest(c("account-logout"))&&(t.preventDefault(),At().catch(r=>{y(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":P("account-login",{});break;case"expired":case"error":P("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(),L.setCheckoutResolver(at),await _(t),V("account",ht()?"logged in":"logged out")}function de(t){return g(t)&&g(t.__core)&&g(t.__parts)}function kt(t,e){let r=Reflect.get(window,"Tether");if(!de(r))throw new Error(`tether.${t}.js runs after the Tether script, which loads it, and needs its window.Tether`);r.__parts[t]=e}kt("account",j);})();
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  (() => {
3
2
  var __defProp = Object.defineProperty;
4
3
  var __export = (target, all) => {
@@ -6,42 +5,41 @@
6
5
  __defProp(target, name, { get: all[name], enumerable: true });
7
6
  };
8
7
 
9
- // src/analytics.js
8
+ // src/analytics.ts
10
9
  var analytics_exports = {};
11
10
  __export(analytics_exports, {
12
11
  startAnalytics: () => startAnalytics
13
12
  });
14
13
 
15
- // tether-core:config.js
16
- var m = window.Tether.__core["config.js"];
17
- var { DEFAULTS, cfg, configure, isConfigured, log, reportError, resolveConfig, toMetafieldIdentifier, 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;
18
17
 
19
- // tether-core:dom.js
20
- var m2 = window.Tether.__core["dom.js"];
21
- var { attr, busy, cdnUrl, emit, formatDate, formatMoney, formatPercent, get, has, hasTemplate, imageUrl, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, repeat, repeatKeyed, sameImage, scoped, sel, setImage, setSelected, setStoreHtml, setText, setTextTracked, show, toAttributes, watchImages } = 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;
22
21
 
23
- // tether-core:cart.js
24
- var m3 = window.Tether.__core["cart.js"];
25
- var { Cart, trapFocus } = m3;
22
+ // tether-core:cart.ts
23
+ var m3 = window.Tether.__core["cart.ts"];
24
+ var [Cart] = m3;
26
25
 
27
- // tether-core:client.js
28
- var m4 = window.Tether.__core["client.js"];
29
- var { TetherError, endpoint, gql, request, unwrap, withContext } = m4;
26
+ // tether-core:product.ts
27
+ var m4 = window.Tether.__core["product.ts"];
28
+ var [scopes] = m4;
30
29
 
31
- // src/analytics-shopify.js
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
32
35
  var BUFFER_SIZE = 500;
33
36
  var CONSENT_SCRIPTS = {
34
37
  "default-banner": "https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js",
35
38
  other: "https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js"
36
39
  };
37
40
  var ANALYTICS_SCRIPT = "https://cdn.shopify.com/storefront/analytics/shopify.js";
38
- function shopifyGlobal() {
39
- const shopify = Reflect.get(window, "Shopify");
40
- return (
41
- /** @type {ShopifyGlobal | undefined} */
42
- shopify
43
- );
44
- }
41
+ var page = () => window;
42
+ var shopifyGlobal = () => page().Shopify;
45
43
  function shopifyOptions() {
46
44
  const shopify = cfg.analytics?.shopify;
47
45
  return typeof shopify === "object" ? shopify : {};
@@ -99,7 +97,12 @@
99
97
  deliver();
100
98
  },
101
99
  addDestination(spec) {
102
- const destination = { name: spec.name, next: 0, subscribers: /* @__PURE__ */ new Map(), context: destinationContext(spec.name) };
100
+ const destination = {
101
+ name: spec.name,
102
+ next: 0,
103
+ subscribers: /* @__PURE__ */ new Map(),
104
+ context: destinationContext(spec.name)
105
+ };
103
106
  Promise.resolve(spec.setup?.({ subscribe: subscriberOf(destination), getConfig: bus2.getConfig })).then(() => {
104
107
  destinations.push(destination);
105
108
  deliver();
@@ -134,11 +137,17 @@
134
137
  async function startShopifyAnalytics(isProductPage) {
135
138
  const existing = shopifyGlobal();
136
139
  if (existing?.analytics) return existing.analytics;
137
- const data = await gql("query TetherShopId { shop { id } }", {}, { context: false });
140
+ const data = await gql(
141
+ "query TetherShopId { shop { id } }",
142
+ {},
143
+ shaped({ shop: { id: "string" } }),
144
+ { context: false }
145
+ );
138
146
  const shopify = shopifyGlobal() ?? {};
139
- Reflect.set(window, "Shopify", shopify);
140
- shopify.country = (cfg.country || "US").toUpperCase();
141
- shopify.locale = (cfg.locale || "en").split("-")[0]?.toLowerCase() ?? "en";
147
+ page().Shopify = shopify;
148
+ shopify.country = cfg.country ?? "US";
149
+ const [language = "en"] = (cfg.locale || "en").split("-");
150
+ shopify.locale = language.toLowerCase();
142
151
  shopify.shop = cfg.domain;
143
152
  shopify.routes = {
144
153
  root: "/",
@@ -158,7 +167,7 @@
158
167
  return bus2;
159
168
  }
160
169
 
161
- // src/analytics.js
170
+ // src/analytics.ts
162
171
  var DEFAULT_VARIANT_TITLE = "Default Title";
163
172
  var CENTS_PER_UNIT = 100;
164
173
  var MAX_LIST_ITEMS = 200;
@@ -243,14 +252,10 @@
243
252
  function mainProduct() {
244
253
  const el = document.querySelector(sel("product"));
245
254
  if (!el || el.closest(`${sel("collection")},${sel("products")},${sel("recommendations")}`)) return null;
246
- const tether = Reflect.get(window, "Tether");
247
- return (
248
- /** @type {{ getScope: (el: Element) => unknown }} */
249
- tether.getScope(el)
250
- );
255
+ return scopes.get(el) ?? null;
251
256
  }
252
257
  function onProductReady({ product, scope }) {
253
- if (!scope || viewed.has(scope.root) || mainProduct() !== scope) return;
258
+ if (viewed.has(scope.root) || mainProduct() !== scope) return;
254
259
  viewed.add(scope.root);
255
260
  const variant = scope.variant ?? product.variants.nodes[0];
256
261
  const items = [itemFromVariant(product, variant)];
@@ -259,7 +264,7 @@
259
264
  products
260
265
  });
261
266
  }
262
- function onListReady({ products = [], collection }) {
267
+ function onListReady({ products, collection }) {
263
268
  const items = products.slice(0, MAX_LIST_ITEMS).map((product, index) => itemFromVariant(product, product.variants.nodes[0], 1, index));
264
269
  const list = { item_list_id: collection?.handle || "products", item_list_name: collection?.title || "Products" };
265
270
  if (!collection) {
@@ -302,6 +307,7 @@
302
307
  send("view_cart", { currency: Cart.state?.cost.totalAmount.currencyCode, value: totalValue(items), items });
303
308
  }
304
309
  function onCheckout({ cart }) {
310
+ if (!cart) return;
305
311
  const items = cart.lines.nodes.map((line) => itemFromLine(line));
306
312
  const coupons = cart.discountCodes.filter((discount) => discount.applicable).map((discount) => discount.code);
307
313
  send("begin_checkout", {
@@ -311,55 +317,30 @@
311
317
  items
312
318
  });
313
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 });
330
+ }
331
+ };
332
+ function report(event, name) {
333
+ REPORTERS[name](event.detail);
334
+ }
314
335
  function handle(event) {
315
- const name = event.type.slice(cfg.prefix.length + 1);
316
- const detail = Reflect.get(event, "detail");
317
- switch (name) {
318
- case "product-ready":
319
- onProductReady(
320
- /** @type {ProductReadyDetail} */
321
- detail
322
- );
323
- break;
324
- case "list-ready":
325
- onListReady(
326
- /** @type {ListReadyDetail} */
327
- detail
328
- );
329
- break;
330
- case "cart-updated":
331
- onCartUpdated(
332
- /** @type {CartUpdatedDetail} */
333
- detail
334
- );
335
- break;
336
- case "cart-toggled":
337
- if (
338
- /** @type {{ open: boolean }} */
339
- detail.open
340
- ) onCartOpened();
341
- break;
342
- case "checkout":
343
- onCheckout(
344
- /** @type {{ cart: AnalyticsCart }} */
345
- detail
346
- );
347
- break;
348
- case "search": {
349
- const { term } = (
350
- /** @type {{ term: string }} */
351
- detail
352
- );
353
- if (term) send("search", { search_term: term }, "search_viewed", { searchTerm: term });
354
- break;
355
- }
356
- case "page":
357
- viewed = /* @__PURE__ */ new WeakSet();
358
- bus?.publish("page_viewed", {});
359
- break;
360
- default:
361
- break;
336
+ if (event.type === "astro:page-load") {
337
+ viewed = /* @__PURE__ */ new WeakSet();
338
+ bus?.publish("page_viewed", {});
339
+ return;
362
340
  }
341
+ ANALYTICS_EVENTS.forEach((name) => {
342
+ if (isOwnEvent(event, name)) report(event, name);
343
+ });
363
344
  }
364
345
  async function startAnalytics(queue) {
365
346
  if (cfg.analytics?.shopify) {
@@ -376,11 +357,23 @@
376
357
  };
377
358
  }
378
359
 
379
- // src/parts/analytics.js
380
- var { Tether } = (
381
- /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */
382
- window
383
- );
384
- if (!Tether) throw new Error("tether.analytics.js runs after the Tether script, which loads it");
385
- Tether.__parts["analytics"] = analytics_exports;
360
+ // server/src/shared/json.ts
361
+ function isRecord(value) {
362
+ return value !== null && typeof value === "object" && !Array.isArray(value);
363
+ }
364
+
365
+ // src/part-registry.ts
366
+ function isTetherInternals(value) {
367
+ return isRecord(value) && isRecord(value["__core"]) && isRecord(value["__parts"]);
368
+ }
369
+ function registerPart(name, part) {
370
+ const tether = Reflect.get(window, "Tether");
371
+ if (!isTetherInternals(tether)) {
372
+ throw new Error(`tether.${name}.js runs after the Tether script, which loads it, and needs its window.Tether`);
373
+ }
374
+ tether.__parts[name] = part;
375
+ }
376
+
377
+ // src/parts/analytics.ts
378
+ registerPart("analytics", analytics_exports);
386
379
  })();
@@ -1 +1 @@
1
- "use strict";(()=>{var U=Object.defineProperty;var D=(t,e)=>{for(var n in e)U(t,n,{get:e[n],enumerable:!0})};var T={};D(T,{startAnalytics:()=>it});var M=window.Tether.__core["config.js"],{DEFAULTS:at,cfg:c,configure:dt,isConfigured:ut,log:v,reportError:l,resolveConfig:lt,toMetafieldIdentifier:pt,warn:ft}=M;var N=window.Tether.__core["dom.js"],{attr:mt,busy:yt,cdnUrl:gt,emit:wt,formatDate:_t,formatMoney:bt,formatPercent:Tt,get:vt,has:Ct,hasTemplate:kt,imageUrl:St,notifyLayoutChanged:xt,parseJSONAttr:Et,productUrl:At,qsa:Lt,repeat:It,repeatKeyed:Pt,sameImage:Rt,scoped:qt,sel:p,setImage:jt,setSelected:Ft,setStoreHtml:Ut,setText:Dt,setTextTracked:Mt,show:Nt,toAttributes:Ot,watchImages:Vt}=N;var O=window.Tether.__core["cart.js"],{Cart:g,trapFocus:Bt}=O;var V=window.Tether.__core["client.js"],{TetherError:Wt,endpoint:Gt,gql:C,request:Jt,unwrap:Kt,withContext:Xt}=V;var $=500,k={"default-banner":"https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js",other:"https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js"},B="https://cdn.shopify.com/storefront/analytics/shopify.js";function m(){return Reflect.get(window,"Shopify")}function x(){let t=c.analytics?.shopify;return typeof t=="object"?t:{}}function E(){try{let t=m()?.customerPrivacy;return t?.consentStatus==="loaded"&&t.currentVisitorConsent?.()?.analytics!=="no"&&!!t.analyticsProcessingAllowed?.()}catch{return!1}}function H(t){let e=`hydrogen:${t}`;return{getTrackingValues:()=>{let n=E()?m()?.customerPrivacy?.__internal:void 0;return{uniqueToken:n?.uniqueToken?.({generateFallback:!0,tag:e})??"",visitToken:n?.visitToken?.({generateFallback:!0,tag:e})??""}}}}var W=t=>(e,n)=>{let o=t.subscribers.get(e)??new Set;return t.subscribers.set(e,o),o.add(n),()=>t.subscribers.get(e)?.delete(n)};function G(t){let e=[],n=[],o={shop:{shopId:t,channel:"headless"},consent:{mode:x().consent||"no-banner"}},r=()=>{if(E())for(let s of e)for(;s.next<n.length;s.next+=1){let i=n[s.next];i&&J(s,i)}},a={getConfig:()=>o,publish(s,i={}){if(n.push({event:s,payload:{shop:o.shop,url:window.location.href,...i}}),n.length>$){n.shift();for(let d of e)d.next=Math.max(0,d.next-1)}r()},addDestination(s){let i={name:s.name,next:0,subscribers:new Map,context:H(s.name)};return Promise.resolve(s.setup?.({subscribe:W(i),getConfig:a.getConfig})).then(()=>{e.push(i),r()}).catch(d=>{l(d,`analytics ${s.name}`)}),()=>{let d=e.indexOf(i);d>=0&&e.splice(d,1)}}};return document.addEventListener("consentTrackingApiLoaded",r),document.addEventListener("visitorConsentCollected",r),a}function J(t,{event:e,payload:n}){t.subscribers.get(e)?.forEach(o=>{try{o(n,t.context)}catch(r){l(r,`analytics ${t.name}`)}})}function S(t){let e=document.createElement("script");e.src=t,e.async=!0,document.head.appendChild(e)}async function A(t){let e=m();if(e?.analytics)return e.analytics;let n=await C("query TetherShopId { shop { id } }",{},{context:!1}),o=m()??{};Reflect.set(window,"Shopify",o),o.country=(c.country||"US").toUpperCase(),o.locale=(c.locale||"en").split("-")[0]?.toLowerCase()??"en",o.shop=c.domain,o.routes={root:"/",match:()=>({pageTemplateName:t()?"product":"page"}),...o.routes};let{proxy:r,consent:a}=x();o.customerPrivacy={...o.customerPrivacy,config:r?{isHeadless:!0,asyncConsent:!0,asyncVisitorState:!0,consentDomain:window.location.host}:{isHeadless:!0,storefrontAccessToken:c.token,checkoutRootDomain:c.domain}};let s=G(n.shop.id);return o.analytics=s,S(a==="default-banner"?k["default-banner"]:k.other),S(B),v("shopify analytics ready",n.shop.id),s}var K="Default Title",L=100,X=200,Y=t=>t?parseFloat(t.amount):0,I=t=>(t??"").split("/").pop()??"";function b(t,e,n=1,o){let r={item_id:e?.sku||I(e?.id)||I(t.id),item_name:t.title,item_variant:e?.title===K?void 0:e?.title,item_brand:t.vendor||void 0,item_category:t.productType||void 0,price:Y(e?.price??t.priceRange?.minVariantPrice),quantity:n};return o!=null&&(r.index=o),r}var y=(t,e=t.quantity)=>b(t.merchandise.product,t.merchandise,e);function f(t){let e=t.reduce((n,o)=>n+o.price*(o.quantity||1),0);return Math.round(e*L)/L}var Z=(t,e,n=1)=>({id:t.id,title:t.title,price:e.price,vendor:t.vendor||"",variantId:e.id,variantTitle:e.title,quantity:n,sku:e.sku||void 0,productType:t.productType||void 0}),P=t=>({id:t.id,quantity:t.quantity,merchandise:{id:t.merchandise.id,title:t.merchandise.title,price:t.merchandise.price,sku:t.merchandise.sku,product:{id:t.merchandise.product.id,title:t.merchandise.product.title,vendor:t.merchandise.product.vendor||"",handle:t.merchandise.product.handle}}});function z(){let{dataLayer:t}=c.analytics??{},e=typeof t=="string"?t:"dataLayer",n=Reflect.get(window,e);if(Array.isArray(n))return n;let o=[];return Reflect.set(window,e,o),o}function Q(t,e){let n=z();if(!e){n.push({event:t});return}n.push({ecommerce:null}),n.push({event:t,ecommerce:e})}var h=null,w=null,q=null,_=new WeakSet;function u(t,e,n,o){c.analytics?.dataLayer&&Q(t,e),h&&n&&h.publish(n,o);try{c.analytics?.onEvent?.(t,e)}catch(r){l(r,"analytics onEvent")}}function j(){let t=document.querySelector(p("product"));return!t||t.closest(`${p("collection")},${p("products")},${p("recommendations")}`)?null:Reflect.get(window,"Tether").getScope(t)}function tt({product:t,scope:e}){if(!e||_.has(e.root)||j()!==e)return;_.add(e.root);let n=e.variant??t.variants.nodes[0],o=[b(t,n)],r=n?[Z(t,n)]:[];u("view_item",{currency:n?.price.currencyCode,value:f(o),items:o},"product_viewed",{products:r})}function et({products:t=[],collection:e}){let n=t.slice(0,X).map((r,a)=>b(r,r.variants.nodes[0],1,a)),o={item_list_id:e?.handle||"products",item_list_name:e?.title||"Products"};if(!e){u("view_item_list",{...o,items:n});return}u("view_item_list",{...o,items:n},"collection_viewed",{collection:{id:e.id,handle:e.handle}})}function nt(t,e,n){let o=t?.cost.totalAmount.currencyCode;e.forEach((r,a)=>{let s=n.get(a),i=r.quantity-(s?.quantity??0);if(i<=0)return;let d=[y(r,i)];u("add_to_cart",{currency:o,value:f(d),items:d},"product_added_to_cart",{cart:t,prevCart:q,currentLine:P(r),prevLine:s?P(s):void 0})}),n.forEach((r,a)=>{let s=r.quantity-(e.get(a)?.quantity??0);if(s<=0)return;let i=[y(r,s)];u("remove_from_cart",{currency:o,value:f(i),items:i})})}function ot({cart:t,reason:e}){let n=new Map((t?.lines.nodes??[]).map(o=>[o.merchandise.id,o]));w&&e!=="load"&&e!=="pending"&&nt(t,n,w),w=n,q=t}function rt(){let t=g.lines.map(e=>y(e));u("view_cart",{currency:g.state?.cost.totalAmount.currencyCode,value:f(t),items:t})}function st({cart:t}){let e=t.lines.nodes.map(o=>y(o)),n=t.discountCodes.filter(o=>o.applicable).map(o=>o.code);u("begin_checkout",{currency:t.cost.totalAmount.currencyCode,value:f(e),coupon:n.join(",")||void 0,items:e})}function R(t){let e=t.type.slice(c.prefix.length+1),n=Reflect.get(t,"detail");switch(e){case"product-ready":tt(n);break;case"list-ready":et(n);break;case"cart-updated":ot(n);break;case"cart-toggled":n.open&&rt();break;case"checkout":st(n);break;case"search":{let{term:o}=n;o&&u("search",{search_term:o},"search_viewed",{searchTerm:o});break}case"page":_=new WeakSet,h?.publish("page_viewed",{});break;default:break}}async function it(t){c.analytics?.shopify&&(h=await A(()=>j()!=null).catch(e=>(l(e,"shopify analytics"),null))),h?.publish("page_viewed",{}),t.splice(0).forEach(R),t.push=(...e)=>(e.forEach(R),t.length)}var{Tether:F}=window;if(!F)throw new Error("tether.analytics.js runs after the Tether script, which loads it");F.__parts.analytics=T;})();
1
+ (()=>{var U=Object.defineProperty;var $=(t,n)=>{for(var e in n)U(t,e,{get:n[e],enumerable:!0})};var k={};$(k,{startAnalytics:()=>yt});var G=window.Tether.__core["config.ts"],[a,bt,_,vt,wt,l,Tt]=G;var W=window.Tether.__core["dom.ts"],[C,_t,Ct,Et,xt,At,Pt,St,Lt,E,Nt,It,Rt,Vt,p,Dt,Mt,qt]=W;var Y=window.Tether.__core["cart.ts"],[b]=Y;var H=window.Tether.__core["product.ts"],[x]=H;var J=window.Tether.__core["client.ts"],[jt,A,Ut,P,$t]=J;var Z=500,S={"default-banner":"https://cdn.shopify.com/shopifycloud/privacy-banner/storefront-banner.js",other:"https://cdn.shopify.com/shopifycloud/consent-tracking-api/v0.2/consent-tracking-api.js"},z="https://cdn.shopify.com/storefront/analytics/shopify.js",N=()=>window,y=()=>N().Shopify;function I(){let t=a.analytics?.shopify;return typeof t=="object"?t:{}}function R(){try{let t=y()?.customerPrivacy;return t?.consentStatus==="loaded"&&t.currentVisitorConsent?.()?.analytics!=="no"&&!!t.analyticsProcessingAllowed?.()}catch{return!1}}function K(t){let n=`hydrogen:${t}`;return{getTrackingValues:()=>{let e=R()?y()?.customerPrivacy?.__internal:void 0;return{uniqueToken:e?.uniqueToken?.({generateFallback:!0,tag:n})??"",visitToken:e?.visitToken?.({generateFallback:!0,tag:n})??""}}}}var X=t=>(n,e)=>{let r=t.subscribers.get(n)??new Set;return t.subscribers.set(n,r),r.add(e),()=>t.subscribers.get(n)?.delete(e)};function Q(t){let n=[],e=[],r={shop:{shopId:t,channel:"headless"},consent:{mode:I().consent||"no-banner"}},o=()=>{if(R())for(let i of n)for(;i.next<e.length;i.next+=1){let s=e[i.next];s&&tt(i,s)}},c={getConfig:()=>r,publish(i,s={}){if(e.push({event:i,payload:{shop:r.shop,url:window.location.href,...s}}),e.length>Z){e.shift();for(let u of n)u.next=Math.max(0,u.next-1)}o()},addDestination(i){let s={name:i.name,next:0,subscribers:new Map,context:K(i.name)};return Promise.resolve(i.setup?.({subscribe:X(s),getConfig:c.getConfig})).then(()=>{n.push(s),o()}).catch(u=>{l(u,`analytics ${i.name}`)}),()=>{let u=n.indexOf(s);u>=0&&n.splice(u,1)}}};return document.addEventListener("consentTrackingApiLoaded",o),document.addEventListener("visitorConsentCollected",o),c}function tt(t,{event:n,payload:e}){t.subscribers.get(n)?.forEach(r=>{try{r(e,t.context)}catch(o){l(o,`analytics ${t.name}`)}})}function L(t){let n=document.createElement("script");n.src=t,n.async=!0,document.head.appendChild(n)}async function V(t){let n=y();if(n?.analytics)return n.analytics;let e=await A("query TetherShopId { shop { id } }",{},P({shop:{id:"string"}}),{context:!1}),r=y()??{};N().Shopify=r,r.country=a.country??"US";let[o="en"]=(a.locale||"en").split("-");r.locale=o.toLowerCase(),r.shop=a.domain,r.routes={root:"/",match:()=>({pageTemplateName:t()?"product":"page"}),...r.routes};let{proxy:c,consent:i}=I();r.customerPrivacy={...r.customerPrivacy,config:c?{isHeadless:!0,asyncConsent:!0,asyncVisitorState:!0,consentDomain:window.location.host}:{isHeadless:!0,storefrontAccessToken:a.token,checkoutRootDomain:a.domain}};let s=Q(e.shop.id);return r.analytics=s,L(i==="default-banner"?S["default-banner"]:S.other),L(z),_("shopify analytics ready",e.shop.id),s}var nt="Default Title",D=100,et=200,rt=t=>t?parseFloat(t.amount):0,M=t=>(t??"").split("/").pop()??"";function T(t,n,e=1,r){let o={item_id:n?.sku||M(n?.id)||M(t.id),item_name:t.title,item_variant:n?.title===nt?void 0:n?.title,item_brand:t.vendor||void 0,item_category:t.productType||void 0,price:rt(n?.price??t.priceRange?.minVariantPrice),quantity:e};return r!=null&&(o.index=r),o}var h=(t,n=t.quantity)=>T(t.merchandise.product,t.merchandise,n);function f(t){let n=t.reduce((e,r)=>e+r.price*(r.quantity||1),0);return Math.round(n*D)/D}var ot=(t,n,e=1)=>({id:t.id,title:t.title,price:n.price,vendor:t.vendor||"",variantId:n.id,variantTitle:n.title,quantity:e,sku:n.sku||void 0,productType:t.productType||void 0}),q=t=>({id:t.id,quantity:t.quantity,merchandise:{id:t.merchandise.id,title:t.merchandise.title,price:t.merchandise.price,sku:t.merchandise.sku,product:{id:t.merchandise.product.id,title:t.merchandise.product.title,vendor:t.merchandise.product.vendor||"",handle:t.merchandise.product.handle}}});function it(){let{dataLayer:t}=a.analytics??{},n=typeof t=="string"?t:"dataLayer",e=Reflect.get(window,n);if(Array.isArray(e))return e;let r=[];return Reflect.set(window,n,r),r}function st(t,n){let e=it();if(!n){e.push({event:t});return}e.push({ecommerce:null}),e.push({event:t,ecommerce:n})}var m=null,v=null,O=null,w=new WeakSet;function d(t,n,e,r){a.analytics?.dataLayer&&st(t,n),m&&e&&m.publish(e,r);try{a.analytics?.onEvent?.(t,n)}catch(o){l(o,"analytics onEvent")}}function F(){let t=document.querySelector(p("product"));return!t||t.closest(`${p("collection")},${p("products")},${p("recommendations")}`)?null:x.get(t)??null}function at({product:t,scope:n}){if(w.has(n.root)||F()!==n)return;w.add(n.root);let e=n.variant??t.variants.nodes[0],r=[T(t,e)],o=e?[ot(t,e)]:[];d("view_item",{currency:e?.price.currencyCode,value:f(r),items:r},"product_viewed",{products:o})}function ct({products:t,collection:n}){let e=t.slice(0,et).map((o,c)=>T(o,o.variants.nodes[0],1,c)),r={item_list_id:n?.handle||"products",item_list_name:n?.title||"Products"};if(!n){d("view_item_list",{...r,items:e});return}d("view_item_list",{...r,items:e},"collection_viewed",{collection:{id:n.id,handle:n.handle}})}function ut(t,n,e){let r=t?.cost.totalAmount.currencyCode;n.forEach((o,c)=>{let i=e.get(c),s=o.quantity-(i?.quantity??0);if(s<=0)return;let u=[h(o,s)];d("add_to_cart",{currency:r,value:f(u),items:u},"product_added_to_cart",{cart:t,prevCart:O,currentLine:q(o),prevLine:i?q(i):void 0})}),e.forEach((o,c)=>{let i=o.quantity-(n.get(c)?.quantity??0);if(i<=0)return;let s=[h(o,i)];d("remove_from_cart",{currency:r,value:f(s),items:s})})}function dt({cart:t,reason:n}){let e=new Map((t?.lines.nodes??[]).map(r=>[r.merchandise.id,r]));v&&n!=="load"&&n!=="pending"&&ut(t,e,v),v=e,O=t}function lt(){let t=b.lines.map(n=>h(n));d("view_cart",{currency:b.state?.cost.totalAmount.currencyCode,value:f(t),items:t})}function pt({cart:t}){if(!t)return;let n=t.lines.nodes.map(r=>h(r)),e=t.discountCodes.filter(r=>r.applicable).map(r=>r.code);d("begin_checkout",{currency:t.cost.totalAmount.currencyCode,value:f(n),coupon:e.join(",")||void 0,items:n})}var ft={"product-ready":at,"list-ready":ct,"cart-updated":dt,"cart-toggled":({open:t})=>{t&&lt()},checkout:pt,search:({term:t})=>{t&&d("search",{search_term:t},"search_viewed",{searchTerm:t})}};function mt(t,n){ft[n](t.detail)}function B(t){if(t.type==="astro:page-load"){w=new WeakSet,m?.publish("page_viewed",{});return}C.forEach(n=>{E(t,n)&&mt(t,n)})}async function yt(t){a.analytics?.shopify&&(m=await V(()=>F()!=null).catch(n=>(l(n,"shopify analytics"),null))),m?.publish("page_viewed",{}),t.splice(0).forEach(B),t.push=(...n)=>(n.forEach(B),t.length)}function g(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)}function ht(t){return g(t)&&g(t.__core)&&g(t.__parts)}function j(t,n){let e=Reflect.get(window,"Tether");if(!ht(e))throw new Error(`tether.${t}.js runs after the Tether script, which loads it, and needs its window.Tether`);e.__parts[t]=n}j("analytics",k);})();
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  (() => {
3
2
  var __defProp = Object.defineProperty;
4
3
  var __export = (target, all) => {
@@ -6,7 +5,7 @@
6
5
  __defProp(target, name, { get: all[name], enumerable: true });
7
6
  };
8
7
 
9
- // src/diagnose.js
8
+ // src/diagnose.ts
10
9
  var diagnose_exports = {};
11
10
  __export(diagnose_exports, {
12
11
  apiVersionStatus: () => apiVersionStatus,
@@ -15,31 +14,31 @@
15
14
  didYouMean: () => didYouMean
16
15
  });
17
16
 
18
- // tether-core:config.js
19
- var m = window.Tether.__core["config.js"];
20
- var { DEFAULTS, cfg, configure, isConfigured, log, reportError, resolveConfig, toMetafieldIdentifier, warn } = m;
17
+ // tether-core:config.ts
18
+ var m = window.Tether.__core["config.ts"];
19
+ var [cfg, isConfigured, log, MARKET_SOURCES, parseMarkets, reportError, warn] = m;
21
20
 
22
- // tether-core:client.js
23
- var m2 = window.Tether.__core["client.js"];
24
- var { TetherError, endpoint, gql, request, unwrap, withContext } = m2;
21
+ // tether-core:client.ts
22
+ var m2 = window.Tether.__core["client.ts"];
23
+ var [endpoint, gql, orNull, shaped, TetherError] = m2;
25
24
 
26
- // tether-core:dom.js
27
- var m3 = window.Tether.__core["dom.js"];
28
- var { attr, busy, cdnUrl, emit, formatDate, formatMoney, formatPercent, get, has, hasTemplate, imageUrl, notifyLayoutChanged, parseJSONAttr, productUrl, qsa, repeat, repeatKeyed, sameImage, scoped, sel, setImage, setSelected, setStoreHtml, setText, setTextTracked, show, toAttributes, watchImages } = m3;
25
+ // tether-core:dom.ts
26
+ var m3 = window.Tether.__core["dom.ts"];
27
+ var [ANALYTICS_EVENTS, attr, attributesFromJson, emit, formatDate, formatMoney, get, has, hasTemplate, isOwnEvent, parseJSONAttr, productUrl, qsa, repeat, sel, setImage, setText, show] = m3;
29
28
 
30
- // tether-core:loader.js
31
- var m4 = window.Tether.__core["loader.js"];
32
- var { clearProductCache, getProduct, getProducts, getRecommendations, hydrateProducts, normalizeProductKey, primeProduct, refreshProducts, takeStale } = m4;
29
+ // tether-core:loader.ts
30
+ var m4 = window.Tether.__core["loader.ts"];
31
+ var [clearProductCache, getProduct] = m4;
33
32
 
34
- // tether-core:selling-plans.js
35
- var m5 = window.Tether.__core["selling-plans.js"];
36
- var { GID, allPlans, allocationFor, findPlan, hasPlans, planAdjustment, planCheckoutCharge, planPrice, planSavings, plansForVariant, toGid } = m5;
33
+ // tether-core:selling-plans.ts
34
+ var m5 = window.Tether.__core["selling-plans.ts"];
35
+ var [allPlans] = m5;
37
36
 
38
- // tether-core:status.js
39
- var m6 = window.Tether.__core["status.js"];
40
- var { STATUS_KEYS, boundary, isNotFound, ownedBy, resolveProductKey, setScopeStatus } = m6;
37
+ // tether-core:status.ts
38
+ var m6 = window.Tether.__core["status.ts"];
39
+ var [boundary, resolveProductKey] = m6;
41
40
 
42
- // src/api-version.js
41
+ // src/api-version.ts
43
42
  var QUARTERLY_VERSION = /^(\d{4})-(01|04|07|10)$/;
44
43
  var MONTHS_PER_QUARTER = 3;
45
44
  var QUARTERS_PER_YEAR = 4;
@@ -84,11 +83,11 @@
84
83
  };
85
84
  }
86
85
 
87
- // tether-core:lazy.js
88
- var m7 = window.Tether.__core["lazy.js"];
89
- var { coreModules, loadPart } = m7;
86
+ // tether-core:lazy.ts
87
+ var m7 = window.Tether.__core["lazy.ts"];
88
+ var [loadPart] = m7;
90
89
 
91
- // src/diagnose-markup.js
90
+ // src/diagnose-markup.ts
92
91
  var SHOW = /* @__PURE__ */ new Set([
93
92
  "in-stock",
94
93
  "out-of-stock",
@@ -336,7 +335,7 @@
336
335
  return problems;
337
336
  }
338
337
 
339
- // src/diagnose.js
338
+ // src/diagnose.ts
340
339
  var MAX_PRODUCTS_CHECKED = 20;
341
340
  var API_UPGRADE_WARNING_MONTHS = 3;
342
341
  var TOKEN_EDGE_CHARACTERS = 4;
@@ -379,6 +378,7 @@
379
378
  if (ok && (monthsLeft === void 0 || monthsLeft >= API_UPGRADE_WARNING_MONTHS)) return null;
380
379
  return { level: ok ? "warn" : "error", message: `apiVersion ${cfg.apiVersion}: ${note}` };
381
380
  }
381
+ var isShopAnswer = shaped({ shop: { name: "string", primaryDomain: { url: "string" }, paymentSettings: { currencyCode: "string" } } });
382
382
  async function checkStorefront() {
383
383
  if (!isConfigured()) return { kind: "not-configured" };
384
384
  const startedAt = Date.now();
@@ -386,6 +386,7 @@
386
386
  const data = await gql(
387
387
  "query TetherDiagnose { shop { name primaryDomain { url } paymentSettings { currencyCode } } }",
388
388
  {},
389
+ isShopAnswer,
389
390
  { context: false }
390
391
  );
391
392
  const shop = {
@@ -460,7 +461,12 @@
460
461
  report.problems.push(...checkOptions(root, key, product));
461
462
  });
462
463
  }
463
- async function diagnose({ root = document, silent = false, version, now = /* @__PURE__ */ new Date() } = {}) {
464
+ async function diagnose({
465
+ root = document,
466
+ silent = false,
467
+ version = "",
468
+ now = /* @__PURE__ */ new Date()
469
+ } = {}) {
464
470
  const storefront = await checkStorefront();
465
471
  const report = {
466
472
  version,
@@ -516,11 +522,23 @@
516
522
  console.groupEnd();
517
523
  }
518
524
 
519
- // src/parts/diagnose.js
520
- var { Tether } = (
521
- /** @type {Window & { Tether?: { __parts: Record<string, unknown> } }} */
522
- window
523
- );
524
- if (!Tether) throw new Error("tether.diagnose.js runs after the Tether script, which loads it");
525
- Tether.__parts["diagnose"] = diagnose_exports;
525
+ // server/src/shared/json.ts
526
+ function isRecord(value) {
527
+ return value !== null && typeof value === "object" && !Array.isArray(value);
528
+ }
529
+
530
+ // src/part-registry.ts
531
+ function isTetherInternals(value) {
532
+ return isRecord(value) && isRecord(value["__core"]) && isRecord(value["__parts"]);
533
+ }
534
+ function registerPart(name, part) {
535
+ const tether = Reflect.get(window, "Tether");
536
+ if (!isTetherInternals(tether)) {
537
+ throw new Error(`tether.${name}.js runs after the Tether script, which loads it, and needs its window.Tether`);
538
+ }
539
+ tether.__parts[name] = part;
540
+ }
541
+
542
+ // src/parts/diagnose.ts
543
+ registerPart("diagnose", diagnose_exports);
526
544
  })();
@@ -1,4 +1,4 @@
1
- "use strict";(()=>{var q=Object.defineProperty;var H=(e,n)=>{for(var t in n)q(e,t,{get:n[t],enumerable:!0})};var E={};H(E,{apiVersionStatus:()=>b,checkMarkup:()=>w,diagnose:()=>be,didYouMean:()=>f});var j=window.Tether.__core["config.js"],{DEFAULTS:Ee,cfg:i,configure:$e,isConfigured:S,log:Se,reportError:ke,resolveConfig:Pe,toMetafieldIdentifier:Te,warn:_e}=j;var G=window.Tether.__core["client.js"],{TetherError:Ae,endpoint:k,gql:P,request:ve,unwrap:Me,withContext:xe}=G;var Y=window.Tether.__core["dom.js"],{attr:p,busy:De,cdnUrl:Ue,emit:Ie,formatDate:Ce,formatMoney:Oe,formatPercent:Ve,get:h,has:qe,hasTemplate:T,imageUrl:He,notifyLayoutChanged:je,parseJSONAttr:Ge,productUrl:Ye,qsa:d,repeat:Be,repeatKeyed:Ke,sameImage:Le,scoped:Qe,sel:l,setImage:We,setSelected:Fe,setStoreHtml:ze,setText:Je,setTextTracked:Xe,show:Ze,toAttributes:et,watchImages:tt}=Y;var B=window.Tether.__core["loader.js"],{clearProductCache:ot,getProduct:_,getProducts:rt,getRecommendations:st,hydrateProducts:at,normalizeProductKey:it,primeProduct:ct,refreshProducts:lt,takeStale:ut}=B;var K=window.Tether.__core["selling-plans.js"],{GID:pt,allPlans:R,allocationFor:ht,findPlan:ft,hasPlans:mt,planAdjustment:gt,planCheckoutCharge:bt,planPrice:yt,planSavings:wt,plansForVariant:Et,toGid:$t}=K;var L=window.Tether.__core["status.js"],{STATUS_KEYS:kt,boundary:A,isNotFound:Pt,ownedBy:Tt,resolveProductKey:g,setScopeStatus:_t}=L;var Q=/^(\d{4})-(01|04|07|10)$/;function M(e){let n=Q.exec(typeof e=="string"?e:"");return n?{year:Number(n[1]),month:Number(n[2])}:null}var W=(e,n)=>`${e}-${String(n).padStart(2,"0")}`;function v(e,n=1){let t=M(e);if(!t)throw new Error(`not a quarterly Shopify API version: ${e}`);let o=t.year*4+(t.month-1)/3+n;return W(Math.floor(o/4),o%4*3+1)}function b(e,n=new Date){if(e==="unstable")return{version:e,ok:!1,note:'"unstable" changes without notice: pin a dated version such as 2026-07'};let t=M(e);if(!t)return{version:e,ok:!1,note:"not a quarterly version (YYYY-01, -04, -07 or -10)"};let o=new Date(Date.UTC(t.year,t.month-1,1)),s=new Date(Date.UTC(t.year,t.month-1+12,1)),r=(s.getTime()-n.getTime())/2630016e3,a=o<=n,c=`supported until about ${s.toISOString().slice(0,7)}`;return a?r<=0?c="no longer supported: Shopify falls back to the oldest supported version. Upgrade (see README)":r<3&&(c=`${c}: plan the upgrade to ${v(e)} or later (see README)`):c="not released yet (release candidate at best)",{version:e,ok:a&&r>0,monthsLeft:Math.round(r),next:v(e),note:c}}var F=window.Tether.__core["lazy.js"],{coreModules:vt,loadPart:x}=F;var N=new Set(["in-stock","out-of-stock","backorder","low-stock","plenty-in-stock","on-sale","not-on-sale","has-variants","single-variant","subscription-available","subscription-unavailable","subscription-only","one-time-available","subscription-selected","one-time-selected","has-savings","loading","ready","error","not-found","cart-empty","cart-filled","cart-has-subscription","cart-no-subscription","cart-has-discount","cart-error","cart-warning","list-empty","list-filled","search-empty","search-results","logged-in","logged-out","orders-empty","orders-loading","addresses-loading","addresses-empty","addresses-error","subscriptions-loading","subscriptions-empty","subscriptions-error"]),D=new Set(["title","description","description-text","vendor","type","handle","published-at","price","total-price","compare-at-price","unit-price","min-price","max-price","discount-percentage","discount-amount","variant-title","variant-id","sku","barcode","stock","quantity","featured-image","variant-image","images","tags","link","url","one-time-price","subscription-price","subscription-savings","subscription-savings-amount","checkout-charge","plan-name","plan-description","plan-group","option-value","swatch","image"]),U=new Set(`account account-bind account-link account-login account-logout add-label add-to-cart adding-text
1
+ (()=>{var L=Object.defineProperty;var Y=(e,n)=>{for(var t in n)L(e,t,{get:n[t],enumerable:!0})};var P={};Y(P,{apiVersionStatus:()=>y,checkMarkup:()=>k,diagnose:()=>ke,didYouMean:()=>f});var G=window.Tether.__core["config.ts"],[a,S,Re,$e,Ae,Te,_e]=G;var B=window.Tether.__core["client.ts"],[R,$,Ne,A,xe]=B;var Q=window.Tether.__core["dom.ts"],[De,p,Oe,Ve,Ue,Ie,m,Ce,T,qe,He,Le,d,Ye,l,Ge,Be,Qe]=Q;var j=window.Tether.__core["loader.ts"],[Ke,_]=j;var K=window.Tether.__core["selling-plans.ts"],[v]=K;var W=window.Tether.__core["status.ts"],[N,h]=W;var F=/^(\d{4})-(01|04|07|10)$/;function M(e){let n=F.exec(typeof e=="string"?e:"");return n?{year:Number(n[1]),month:Number(n[2])}:null}var z=(e,n)=>`${e}-${String(n).padStart(2,"0")}`;function x(e,n=1){let t=M(e);if(!t)throw new Error(`not a quarterly Shopify API version: ${e}`);let r=t.year*4+(t.month-1)/3+n;return z(Math.floor(r/4),r%4*3+1)}function y(e,n=new Date){if(e==="unstable")return{version:e,ok:!1,note:'"unstable" changes without notice: pin a dated version such as 2026-07'};let t=M(e);if(!t)return{version:e,ok:!1,note:"not a quarterly version (YYYY-01, -04, -07 or -10)"};let r=new Date(Date.UTC(t.year,t.month-1,1)),s=new Date(Date.UTC(t.year,t.month-1+12,1)),o=(s.getTime()-n.getTime())/2630016e3,i=r<=n,c=`supported until about ${s.toISOString().slice(0,7)}`;return i?o<=0?c="no longer supported: Shopify falls back to the oldest supported version. Upgrade (see README)":o<3&&(c=`${c}: plan the upgrade to ${x(e)} or later (see README)`):c="not released yet (release candidate at best)",{version:e,ok:i&&o>0,monthsLeft:Math.round(o),next:x(e),note:c}}var J=window.Tether.__core["lazy.ts"],[D]=J;var O=new Set(["in-stock","out-of-stock","backorder","low-stock","plenty-in-stock","on-sale","not-on-sale","has-variants","single-variant","subscription-available","subscription-unavailable","subscription-only","one-time-available","subscription-selected","one-time-selected","has-savings","loading","ready","error","not-found","cart-empty","cart-filled","cart-has-subscription","cart-no-subscription","cart-has-discount","cart-error","cart-warning","list-empty","list-filled","search-empty","search-results","logged-in","logged-out","orders-empty","orders-loading","addresses-loading","addresses-empty","addresses-error","subscriptions-loading","subscriptions-empty","subscriptions-error"]),V=new Set(["title","description","description-text","vendor","type","handle","published-at","price","total-price","compare-at-price","unit-price","min-price","max-price","discount-percentage","discount-amount","variant-title","variant-id","sku","barcode","stock","quantity","featured-image","variant-image","images","tags","link","url","one-time-price","subscription-price","subscription-savings","subscription-savings-amount","checkout-charge","plan-name","plan-description","plan-group","option-value","swatch","image"]),U=new Set(`account account-bind account-link account-login account-logout add-label add-to-cart adding-text
2
2
  always-enabled bind cart-checkout-charge cart-clear cart-close cart-count cart-discounts cart-drawer cart-label cart-lines
3
3
  cart-note cart-open cart-subtotal cart-total cart-warning checkout code collection collection-bind countries country
4
4
  country-bind country-label country-select default-plan default-purchase discount discount-code discount-form discount-input
@@ -11,4 +11,4 @@
11
11
  plan-value product products purchase purchase-mode qty qty-minus qty-plus quantity recommendations reverse search
12
12
  search-bind search-collections search-input search-limit search-min search-products search-queries search-results
13
13
  search-state show soldout-text sort state subscribe-text variant variant-select variant-url max-width max-height crop
14
- sig label hydrated busy`.split(/\s+/).filter(Boolean)),z=["bind","option-list","option","variant-select","add-to-cart","purchase","plan-list","plan","qty","line-attribute"],J=["option-list","plan-list","cart-lines","list"],y="metafield:",X=/^image:\d+$/,Z=2;function ee(e,n){let t=Array.from({length:n.length+1},(o,s)=>s);for(let o=1;o<=e.length;o++){let s=[o];for(let r=1;r<=n.length;r++){let a=(t[r-1]??0)+(e[o-1]===n[r-1]?0:1);s.push(Math.min((t[r]??0)+1,(s[r-1]??0)+1,a))}t=s}return t[n.length]??0}function f(e,n,t=""){let o=null,s=1/0;for(let a of n){let c=ee(e,a);c<s&&(s=c,o=a)}let r=Math.max(2,Math.floor(e.length/4));return o!==null&&s<=r?` Did you mean "${t}${o}"?`:""}function te(e){let n=e.id?`#${e.id}`:"",t=e.className&&typeof e.className=="string"?e.className.trim().split(/\s+/):[],o=t.length?`.${t.slice(0,Z).join(".")}`:"";return`<${e.tagName.toLowerCase()}${n}${o}>`}var I=()=>`${l("collection")},${l("products")},${l("recommendations")}`;function ne(e,n){d(e,l("product")).forEach(t=>{if(t.closest(I())&&t.closest(l("list")))return;let{key:o,fromUrl:s,raw:r}=g(t);r?s&&!o&&n("warn",`${p("product")}="${r}" but this URL has no value for it (e.g. ?handle=my-product).`,t):n("error",`${p("product")} has no value. Bind it to the Shopify handle (CMS field), or use "url:handle".`,t)})}function oe(e,n){for(let t of z)d(e,l(t)).forEach(o=>{o.closest(l("product"))||t==="line-attribute"&&o.closest(l("group"))||n("warn",`${p(t)} outside any ${p("product")}: it does nothing here.`,o)});d(e,l("group-add")).forEach(t=>{t.closest(l("group"))||n("warn",`${p("group-add")} outside a ${p("group")}.`,t)});for(let t of J)d(e,l(t)).forEach(o=>{!o.firstElementChild&&!T(o)&&n("warn",`${p(t)} without a template child: put one example element inside it.`,o)});d(e,I()).forEach(t=>{d(t,l("list")).length||n("error",`List without a ${p("list")} child: products have nowhere to render.`,t)})}function re(e,n){d(e,l("show")).forEach(t=>{let o=h(t,"show")??"";N.has(o)||n("warn",`Unknown ${p("show")}="${o}".${f(o,N)}`,t)}),d(e,l("bind")).forEach(t=>{let o=h(t,"bind")||"";!o||D.has(o)||X.test(o)||o.startsWith(y)||n("warn",`Unknown ${p("bind")}="${o}": it stays empty.${f(o,D)}`,t)})}function se(e,n){d(e,l("bind")).forEach(t=>{let o=h(t,"bind")||"";if(!o.startsWith(y))return;let s=o.slice(y.length);i.metafields.some(a=>(typeof a=="string"?a:`${a.namespace}.${a.key}`)===s)||n("error",`${p("bind")}="${o}" but "${s}" is not in config.metafields, so it stays empty.`,t)})}function ae(e,n){let t=`${i.prefix}-`,o=new Set;d(e,"*").forEach(s=>{for(let{name:r}of s.attributes){if(!r.startsWith(t))continue;let a=r.slice(t.length);U.has(a)||o.has(a)||(o.add(a),n("warn",`Unknown attribute ${r}: Tether ignores it.${f(a,U,t)}`,s))}})}function ie(e,n){let t=d(e,l("cart-drawer")).length;d(e,l("cart-open")).length&&!t&&n("warn",`${p("cart-open")} exists but there is no ${p("cart-drawer")} on this page.`),t>1&&n("warn",`More than one ${p("cart-drawer")}.`),d(e,`[${p("state")}="error"]`).forEach(o=>{o.matches(A())&&n("error",`Scope failed to load (${h(o,"error")||"error"}).`,o)})}function w(e=document){let n=[],t=(o,s,r)=>{n.push(r?{level:o,message:s,element:te(r),el:r}:{level:o,message:s})};return ne(e,t),oe(e,t),re(e,t),ae(e,t),se(e,t),ie(e,t),n}var ce=20,le=3,C=4;function ue(e){return e?`${e.slice(0,C)}\u2026${e.slice(-C)} (${e.length} chars)`:"(missing)"}function O(e,n){if(e instanceof Error&&e.message)return e.message;let t=typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0;return typeof t=="string"&&t?t:n}function de(){return{domain:i.domain||"(missing)",token:ue(i.token),apiVersion:i.apiVersion,endpoint:i.domain?k():null,country:i.country,language:i.language,locale:i.locale,markets:i.markets,prefix:i.prefix,productPath:i.productPath,metafields:i.metafields,autoMount:i.autoMount,observe:i.observe,onError:typeof i.onError=="function"}}async function pe(){return{country:i.country||null,language:i.language||null,locale:i.locale||null,detected:i.markets?.detect?(await x("markets")).detectMarket(i.markets):null}}function he({ok:e,monthsLeft:n,note:t}){return e&&(n===void 0||n>=le)?null:{level:e?"warn":"error",message:`apiVersion ${i.apiVersion}: ${t}`}}async function fe(){if(!S())return{kind:"not-configured"};let e=Date.now();try{let n=await P("query TetherDiagnose { shop { name primaryDomain { url } paymentSettings { currencyCode } } }",{},{context:!1});return{kind:"reachable",shop:{name:n.shop.name,url:n.shop.primaryDomain.url,currency:n.shop.paymentSettings.currencyCode},latencyMs:Date.now()-e}}catch(n){return{kind:"unreachable",error:n,latencyMs:Date.now()-e}}}function me(e,n,t){let o=[],s=t.options.map(a=>a.name),r=d(e,l("product")).filter(a=>g(a).key===n&&a.querySelector(l("add-to-cart")));for(let a of r){let c=new Set(d(a,`${l("option-list")},select${l("option")}`).map(u=>h(u,"option-list")||h(u,"option")));if(!(!c.size&&d(a,`select${l("variant-select")}`).length)){if(!i.language)for(let u of c)!u||s.includes(u)||o.push({level:"warn",message:`Product "${t.handle}" has no option "${u}" (its options: ${s.join(", ")||"none"}).${f(u,s)}`});for(let u of t.options)u.optionValues.length<=1||c.has(u.name)||o.push({level:"warn",message:`Product "${t.handle}": option "${u.name}" (${u.optionValues.length} values) has no tether-option-list, so visitors can't choose it.`})}}return o}async function ge(e,n){let t=d(e,l("product")).map(r=>g(r).key),o=[...new Set(t.filter(r=>r!==null&&r!==""))].slice(0,ce);(await Promise.allSettled(o.map(r=>_(r)))).forEach((r,a)=>{let c=o[a]??"";if(r.status==="rejected"){let m=O(r.reason,"not loaded");n.products.push({key:c,error:r.reason instanceof Error?r.reason.message:void 0}),n.problems.push({level:"error",message:`Product "${c}": ${m}. Is it published to the Headless channel?`});return}let u=r.value,$=R(u);n.products.push({key:c,handle:u.handle,title:u.title,plans:$.length,requiresSellingPlan:u.requiresSellingPlan});for(let m of $)n.sellingPlans.push({product:u.handle,group:m.group.name,plan:m.name,id:m.id});n.problems.push(...me(e,c,u))})}async function be({root:e=document,silent:n=!1,version:t,now:o=new Date}={}){let s=await fe(),r={version:t,config:de(),apiVersion:b(i.apiVersion,o),market:await pe(),reachable:s.kind==="reachable",shop:s.kind==="reachable"?s.shop:null,latencyMs:s.kind==="not-configured"?null:s.latencyMs,products:[],sellingPlans:[],problems:[]};switch(s.kind){case"not-configured":r.problems.push({level:"error",message:"TETHER_CONFIG needs domain and token."});break;case"unreachable":r.problems.push({level:"error",message:`Storefront API not reachable: ${O(s.error,"unknown error")}`});break;case"reachable":await ge(e,r);break}let a=he(r.apiVersion);return a&&r.problems.push(a),typeof document<"u"&&r.problems.push(...w(e)),n||ye(r),r}function ye(e){let n=e.problems.filter(c=>c.level==="error").length,t=e.problems.length-n;console.group(`[${i.prefix}] diagnose: ${n?`${n} error(s)`:"no errors"}, ${t} warning(s)`),console.log("version",e.version,"| API",e.apiVersion.version,`(${e.apiVersion.note})`),console.log("config",e.config);let{country:o,language:s,detected:r}=e.market,a=[o,s].filter(Boolean).join(" / ")||"the store default";console.log("market",`in use: ${a}`,r?`(detection picks ${JSON.stringify(r)})`:""),console.log(e.shop?`Storefront API reachable: ${e.shop.name} (${e.latencyMs??0} ms)`:"Storefront API NOT reachable"),e.products.length&&console.table(e.products),e.sellingPlans.length?console.table(e.sellingPlans):e.reachable&&console.log("No selling plans on the products of this page.");for(let c of e.problems)c.level==="error"?console.error(c.message,c.el??""):console.warn(c.message,c.el??"");console.groupEnd()}var{Tether:V}=window;if(!V)throw new Error("tether.diagnose.js runs after the Tether script, which loads it");V.__parts.diagnose=E;})();
14
+ sig label hydrated busy`.split(/\s+/).filter(Boolean)),X=["bind","option-list","option","variant-select","add-to-cart","purchase","plan-list","plan","qty","line-attribute"],Z=["option-list","plan-list","cart-lines","list"],w="metafield:",ee=/^image:\d+$/,te=2;function ne(e,n){let t=Array.from({length:n.length+1},(r,s)=>s);for(let r=1;r<=e.length;r++){let s=[r];for(let o=1;o<=n.length;o++){let i=(t[o-1]??0)+(e[r-1]===n[o-1]?0:1);s.push(Math.min((t[o]??0)+1,(s[o-1]??0)+1,i))}t=s}return t[n.length]??0}function f(e,n,t=""){let r=null,s=1/0;for(let i of n){let c=ne(e,i);c<s&&(s=c,r=i)}let o=Math.max(2,Math.floor(e.length/4));return r!==null&&s<=o?` Did you mean "${t}${r}"?`:""}function re(e){let n=e.id?`#${e.id}`:"",t=e.className&&typeof e.className=="string"?e.className.trim().split(/\s+/):[],r=t.length?`.${t.slice(0,te).join(".")}`:"";return`<${e.tagName.toLowerCase()}${n}${r}>`}var I=()=>`${l("collection")},${l("products")},${l("recommendations")}`;function oe(e,n){d(e,l("product")).forEach(t=>{if(t.closest(I())&&t.closest(l("list")))return;let{key:r,fromUrl:s,raw:o}=h(t);o?s&&!r&&n("warn",`${p("product")}="${o}" but this URL has no value for it (e.g. ?handle=my-product).`,t):n("error",`${p("product")} has no value. Bind it to the Shopify handle (CMS field), or use "url:handle".`,t)})}function se(e,n){for(let t of X)d(e,l(t)).forEach(r=>{r.closest(l("product"))||t==="line-attribute"&&r.closest(l("group"))||n("warn",`${p(t)} outside any ${p("product")}: it does nothing here.`,r)});d(e,l("group-add")).forEach(t=>{t.closest(l("group"))||n("warn",`${p("group-add")} outside a ${p("group")}.`,t)});for(let t of Z)d(e,l(t)).forEach(r=>{!r.firstElementChild&&!T(r)&&n("warn",`${p(t)} without a template child: put one example element inside it.`,r)});d(e,I()).forEach(t=>{d(t,l("list")).length||n("error",`List without a ${p("list")} child: products have nowhere to render.`,t)})}function ie(e,n){d(e,l("show")).forEach(t=>{let r=m(t,"show")??"";O.has(r)||n("warn",`Unknown ${p("show")}="${r}".${f(r,O)}`,t)}),d(e,l("bind")).forEach(t=>{let r=m(t,"bind")||"";!r||V.has(r)||ee.test(r)||r.startsWith(w)||n("warn",`Unknown ${p("bind")}="${r}": it stays empty.${f(r,V)}`,t)})}function ae(e,n){d(e,l("bind")).forEach(t=>{let r=m(t,"bind")||"";if(!r.startsWith(w))return;let s=r.slice(w.length);a.metafields.some(i=>(typeof i=="string"?i:`${i.namespace}.${i.key}`)===s)||n("error",`${p("bind")}="${r}" but "${s}" is not in config.metafields, so it stays empty.`,t)})}function ce(e,n){let t=`${a.prefix}-`,r=new Set;d(e,"*").forEach(s=>{for(let{name:o}of s.attributes){if(!o.startsWith(t))continue;let i=o.slice(t.length);U.has(i)||r.has(i)||(r.add(i),n("warn",`Unknown attribute ${o}: Tether ignores it.${f(i,U,t)}`,s))}})}function le(e,n){let t=d(e,l("cart-drawer")).length;d(e,l("cart-open")).length&&!t&&n("warn",`${p("cart-open")} exists but there is no ${p("cart-drawer")} on this page.`),t>1&&n("warn",`More than one ${p("cart-drawer")}.`),d(e,`[${p("state")}="error"]`).forEach(r=>{r.matches(N())&&n("error",`Scope failed to load (${m(r,"error")||"error"}).`,r)})}function k(e=document){let n=[],t=(r,s,o)=>{n.push(o?{level:r,message:s,element:re(o),el:o}:{level:r,message:s})};return oe(e,t),se(e,t),ie(e,t),ce(e,t),ae(e,t),le(e,t),n}var ue=20,de=3,C=4;function pe(e){return e?`${e.slice(0,C)}\u2026${e.slice(-C)} (${e.length} chars)`:"(missing)"}function q(e,n){if(e instanceof Error&&e.message)return e.message;let t=typeof e=="object"&&e!==null?Reflect.get(e,"code"):void 0;return typeof t=="string"&&t?t:n}function me(){return{domain:a.domain||"(missing)",token:pe(a.token),apiVersion:a.apiVersion,endpoint:a.domain?R():null,country:a.country,language:a.language,locale:a.locale,markets:a.markets,prefix:a.prefix,productPath:a.productPath,metafields:a.metafields,autoMount:a.autoMount,observe:a.observe,onError:typeof a.onError=="function"}}async function fe(){return{country:a.country||null,language:a.language||null,locale:a.locale||null,detected:a.markets?.detect?(await D("markets")).detectMarket(a.markets):null}}function ge({ok:e,monthsLeft:n,note:t}){return e&&(n===void 0||n>=de)?null:{level:e?"warn":"error",message:`apiVersion ${a.apiVersion}: ${t}`}}var he=A({shop:{name:"string",primaryDomain:{url:"string"},paymentSettings:{currencyCode:"string"}}});async function be(){if(!S())return{kind:"not-configured"};let e=Date.now();try{let n=await $("query TetherDiagnose { shop { name primaryDomain { url } paymentSettings { currencyCode } } }",{},he,{context:!1});return{kind:"reachable",shop:{name:n.shop.name,url:n.shop.primaryDomain.url,currency:n.shop.paymentSettings.currencyCode},latencyMs:Date.now()-e}}catch(n){return{kind:"unreachable",error:n,latencyMs:Date.now()-e}}}function ye(e,n,t){let r=[],s=t.options.map(i=>i.name),o=d(e,l("product")).filter(i=>h(i).key===n&&i.querySelector(l("add-to-cart")));for(let i of o){let c=new Set(d(i,`${l("option-list")},select${l("option")}`).map(u=>m(u,"option-list")||m(u,"option")));if(!(!c.size&&d(i,`select${l("variant-select")}`).length)){if(!a.language)for(let u of c)!u||s.includes(u)||r.push({level:"warn",message:`Product "${t.handle}" has no option "${u}" (its options: ${s.join(", ")||"none"}).${f(u,s)}`});for(let u of t.options)u.optionValues.length<=1||c.has(u.name)||r.push({level:"warn",message:`Product "${t.handle}": option "${u.name}" (${u.optionValues.length} values) has no tether-option-list, so visitors can't choose it.`})}}return r}async function we(e,n){let t=d(e,l("product")).map(o=>h(o).key),r=[...new Set(t.filter(o=>o!==null&&o!==""))].slice(0,ue);(await Promise.allSettled(r.map(o=>_(o)))).forEach((o,i)=>{let c=r[i]??"";if(o.status==="rejected"){let g=q(o.reason,"not loaded");n.products.push({key:c,error:o.reason instanceof Error?o.reason.message:void 0}),n.problems.push({level:"error",message:`Product "${c}": ${g}. Is it published to the Headless channel?`});return}let u=o.value,E=v(u);n.products.push({key:c,handle:u.handle,title:u.title,plans:E.length,requiresSellingPlan:u.requiresSellingPlan});for(let g of E)n.sellingPlans.push({product:u.handle,group:g.group.name,plan:g.name,id:g.id});n.problems.push(...ye(e,c,u))})}async function ke({root:e=document,silent:n=!1,version:t="",now:r=new Date}={}){let s=await be(),o={version:t,config:me(),apiVersion:y(a.apiVersion,r),market:await fe(),reachable:s.kind==="reachable",shop:s.kind==="reachable"?s.shop:null,latencyMs:s.kind==="not-configured"?null:s.latencyMs,products:[],sellingPlans:[],problems:[]};switch(s.kind){case"not-configured":o.problems.push({level:"error",message:"TETHER_CONFIG needs domain and token."});break;case"unreachable":o.problems.push({level:"error",message:`Storefront API not reachable: ${q(s.error,"unknown error")}`});break;case"reachable":await we(e,o);break}let i=ge(o.apiVersion);return i&&o.problems.push(i),typeof document<"u"&&o.problems.push(...k(e)),n||Pe(o),o}function Pe(e){let n=e.problems.filter(c=>c.level==="error").length,t=e.problems.length-n;console.group(`[${a.prefix}] diagnose: ${n?`${n} error(s)`:"no errors"}, ${t} warning(s)`),console.log("version",e.version,"| API",e.apiVersion.version,`(${e.apiVersion.note})`),console.log("config",e.config);let{country:r,language:s,detected:o}=e.market,i=[r,s].filter(Boolean).join(" / ")||"the store default";console.log("market",`in use: ${i}`,o?`(detection picks ${JSON.stringify(o)})`:""),console.log(e.shop?`Storefront API reachable: ${e.shop.name} (${e.latencyMs??0} ms)`:"Storefront API NOT reachable"),e.products.length&&console.table(e.products),e.sellingPlans.length?console.table(e.sellingPlans):e.reachable&&console.log("No selling plans on the products of this page.");for(let c of e.problems)c.level==="error"?console.error(c.message,c.el??""):console.warn(c.message,c.el??"");console.groupEnd()}function b(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Ee(e){return b(e)&&b(e.__core)&&b(e.__parts)}function H(e,n){let t=Reflect.get(window,"Tether");if(!Ee(t))throw new Error(`tether.${e}.js runs after the Tether script, which loads it, and needs its window.Tether`);t.__parts[e]=n}H("diagnose",P);})();