@glideidentity/web-client-sdk 6.0.1 → 6.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- !function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.GlideWebClientSDK=n():e.GlideWebClientSDK=n()}(this,()=>(()=>{"use strict";var e={d:(n,t)=>{for(var i in t)e.o(t,i)&&!e.o(n,i)&&Object.defineProperty(n,i,{enumerable:!0,get:t[i]})},o:(e,n)=>Object.prototype.hasOwnProperty.call(e,n),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},n={};e.r(n),e.d(n,{AUTHENTICATION_STRATEGY:()=>i,AuthModal:()=>y,ERROR_CODES:()=>s,PhoneAuthClient:()=>E,USE_CASE:()=>t,createAuthError:()=>h,createQRCodeDataFromDesktop:()=>x,getUserMessage:()=>p,isAuthCredential:()=>C,isAuthError:()=>d,isCancellable:()=>_,isClientError:()=>c,isDesktopData:()=>O,isDesktopStrategy:()=>R,isErrorResponse:()=>L,isGetPhoneNumberResponse:()=>T,isInvokeResult:()=>k,isLinkData:()=>N,isLinkStrategy:()=>A,isRetryableError:()=>g,isTS43Data:()=>I,isTS43Strategy:()=>S,isVerifyPhoneNumberResponse:()=>P,validatePhoneNumber:()=>r,validatePlmn:()=>a});const t={GET_PHONE_NUMBER:"GetPhoneNumber",VERIFY_PHONE_NUMBER:"VerifyPhoneNumber"},i={TS43:"ts43",LINK:"link",DESKTOP:"desktop"},o=/^\+[1-9]\d{1,14}$/;function r(e){return e?e.startsWith("+")?e.length<8?{valid:!1,error:"Phone number too short for E.164 format (minimum 8 characters including +)"}:e.length>16?{valid:!1,error:"Phone number too long for E.164 format (maximum 15 digits after +)"}:/^\+\d+$/.test(e)?o.test(e)?{valid:!0}:{valid:!1,error:"Invalid E.164 phone number format"}:{valid:!1,error:"Phone number contains invalid characters. E.164 format only allows + followed by digits"}:{valid:!1,error:"Phone number must be in E.164 format (start with +)"}:{valid:!0}}function a(e){if(!e)return{valid:!0};const{mcc:n,mnc:t}=e;return n&&/^\d{3}$/.test(n)?t&&/^\d{2,3}$/.test(t)?{valid:!0}:{valid:!1,error:"MNC must be 2 or 3 digits"}:{valid:!1,error:"MCC must be exactly 3 digits"}}const s={INVALID_PHONE_NUMBER:"INVALID_PHONE_NUMBER",INVALID_PLMN:"INVALID_PLMN",MISSING_PARAMETERS:"MISSING_PARAMETERS",BROWSER_NOT_SUPPORTED:"BROWSER_NOT_SUPPORTED",UNSUPPORTED_STRATEGY:"UNSUPPORTED_STRATEGY",USER_CANCELLED:"USER_CANCELLED",CANCELLED:"CANCELLED",VERIFICATION_FAILED:"VERIFICATION_FAILED",NETWORK_ERROR:"NETWORK_ERROR",TIMEOUT:"TIMEOUT",INVALID_RESPONSE:"INVALID_RESPONSE"},l={[s.INVALID_PHONE_NUMBER]:"Please enter a valid phone number in E.164 format (e.g., +14155551234).",[s.INVALID_PLMN]:"Invalid carrier information provided.",[s.MISSING_PARAMETERS]:"Required information is missing.",[s.BROWSER_NOT_SUPPORTED]:"Your browser does not support this authentication method. Please use Chrome or Edge with the Digital Credentials flag enabled.",[s.UNSUPPORTED_STRATEGY]:"This authentication strategy is not supported.",[s.USER_CANCELLED]:"Authentication was cancelled.",[s.CANCELLED]:"Authentication was cancelled.",[s.VERIFICATION_FAILED]:"Verification failed. Please try again.",[s.NETWORK_ERROR]:"Network connection failed. Please check your connection and try again.",[s.TIMEOUT]:"Request timed out. Please try again.",[s.INVALID_RESPONSE]:"Invalid response received."};function d(e){return null!==e&&"object"==typeof e&&"code"in e&&"message"in e&&"string"==typeof e.code&&"string"==typeof e.message}function c(e){return Object.values(s).includes(e.code)}function g(e){return e.code===s.NETWORK_ERROR||e.code===s.TIMEOUT}function p(e){return c(e)&&l[e.code]||e.message}function h(e,n,t){const i=new Error(n||l[e]||e);return i.code=e,i.details=t,i.timestamp=(new Date).toISOString(),i}const u=/(\+?[1-9]\d{6,14})/g,b=/(eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*)/g,m=/session[_-]?key["']?\s*[:=]\s*["']?([a-zA-Z0-9_-]{20,})["']?/gi;function f(e){if(null==e)return e;if("string"==typeof e){let n=e;return n=n.replace(u,e=>e.length<8?e:e.slice(0,2)+"***"+e.slice(-4)),n=n.replace(b,"[JWT]"),n=n.replace(m,(e,n)=>e.replace(n,n.slice(0,4)+"***"+n.slice(-4))),n}if(Array.isArray(e))return e.map(f);if("object"==typeof e){const n={};for(const[t,i]of Object.entries(e))["phone_number","phoneNumber","credential","token","password","secret"].some(e=>t.toLowerCase().includes(e.toLowerCase()))?n[t]="string"==typeof i?"[REDACTED]":i:n[t]=f(i);return n}return e}function v(e){const{sessionKey:n,interval:t=2e3,maxAttempts:i=30,pollingEndpoint:o,statusUrl:r,logger:a,headers:l}=e;let d,c,g=0,p=!1,u=!1;function b(){u=!1,d&&(clearInterval(d),d=void 0)}return{start:function(){return new Promise((e,s)=>{c=s,u=!0,g=0;const h=async()=>{if(u&&!p){if(g>=i)return b(),a?.warn("Polling timeout reached",{attempts:g,maxAttempts:i}),void e({status:"expired",message:"Authentication timeout"});try{const t=o?(a?.debug("Using developer config endpoint for polling",{pollingEndpoint:o}),`${o}/${n}`):r?(a?.debug("Using backend status_url for polling",{statusUrl:r}),r):(a?.debug("Using prod fallback for status polling"),`https://api.glideidentity.app/public/status/${n}`);a?.debug("Polling status",{url:t,attempt:g+1,maxAttempts:i});const s=await fetch(t,{method:"GET",headers:{Accept:"application/json",...l}});if(200===s.status){const t=await s.json();if("completed"===t.status){b(),a?.info("Authentication completed");const i=t.credential||n;return void e({status:"completed",credential:i,session:t.session||{session_key:n}})}g++}else if(410===s.status){b();const n=await s.json().catch(()=>({}));e({status:"expired",message:n.message||"Session expired"})}else if(422===s.status){b();const n=await s.json().catch(()=>({}));e({status:"error",message:n.message||"Authentication failed"})}else 404===s.status?(b(),e({status:"error",message:"Session not found"})):g++}catch(e){a?.debug("Polling error, retrying",{error:e,attempt:g+1}),g++}}};h(),d=setInterval(h,t)})},stop:b,cancel:function(){a?.debug("Polling cancelled"),p=!0,b(),c&&(c(h(s.CANCELLED,"Authentication cancelled")),c=void 0)},isPolling:function(){return void 0!==d},cleanup:function(){b(),p=!1,c=void 0}}}class y{constructor(e){this.container=null,this.backdrop=null,this.isOpen=!1,this.currentStep="os-choice",this.qrCodeData=null,this.statusMessage="",this.originalBodyOverflow="",this.isClosing=!1,this.iconApple='<svg class="glide-icon glide-icon-os" viewBox="0 0 384 512" fill="currentColor"><path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 52.3-11.4 69.5-34.3z"/></svg>',this.iconAndroid='<svg class="glide-icon glide-icon-os" viewBox="0 0 576 512" fill="currentColor"><path d="M420.55,301.93a24,24,0,1,1,24-24,24,24,0,0,1-24,24m-265.1,0a24,24,0,1,1,24-24,24,24,0,0,1-24,24m273.7-144.48,47.94-83a10,10,0,1,0-17.27-10h0l-48.54,84.07a301.25,301.25,0,0,0-246.56,0L116.18,64.45a10,10,0,1,0-17.27,10h0l47.94,83C64.53,202.22,8.24,285.55,0,384H576c-8.24-98.45-64.54-181.78-146.85-226.55"/></svg>',this.iconBack='<svg class="glide-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>',this.options=e||{},this.theme=this.options.theme||"auto",this.handleEscapeKey=this.handleEscapeKey.bind(this)}shouldUseDarkMode(){return"dark"===this.theme||"light"!==this.theme&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches}handleEscapeKey(e){"Escape"===e.key&&this.isOpen&&!1!==this.options?.closeOnEscape&&(this.closeCallback?.(),this.close())}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}showQRCode(e,n="Scan with your phone camera"){this.qrCodeData=e,this.statusMessage=n;const t=this.options.viewMode||"toggle";if("string"==typeof e)this.renderToggleMode(e,n);else switch(t){case"dual":this.renderDualMode(e,n);break;case"pre-step":this.renderPreStepMode(e,n);break;default:this.renderToggleMode(e,n)}this.show()}updateStatus(e,n=!1){if(this.statusMessage=e,this.container){const t=this.container.querySelector("#glide-status");t&&(t.textContent=e,t.style.color=n?"#ff3b30":"")}}setCloseCallback(e){this.closeCallback=e}renderToggleMode(e,n){let t="",i="";"string"==typeof e?(t=e,i=e):(t=e.iosQRCode,i=e.androidQRCode||e.iosQRCode);const o=`\n <div class="glide-content">\n <div class="glide-toggle" id="glide-toggle" data-active="ios">\n <div class="glide-toggle-slider"></div>\n <button class="glide-btn glide-toggle-btn active" data-platform="ios">${this.iconApple}<span>iOS</span></button>\n <button class="glide-btn glide-toggle-btn" data-platform="android">${this.iconAndroid}<span>Android</span></button>\n </div>\n\n <div class="glide-qr-area">\n <img \n class="glide-qr-img"\n id="glide-qr-img" \n src="${this.escapeHtml(t)}" \n alt="QR Code" \n class="glide-qr-img" \n data-ios="${this.escapeHtml(t)}"\n data-android="${this.escapeHtml(i)}"\n />\n \n \x3c!-- Animation Overlay (Inside QR Area for centering) --\x3e\n <div id="glide-phone-overlay" class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n </div>\n </div>\n `;this.createModal(o,"",!0),this.setupPlatformToggles(),this.setupHelpInteraction()}renderDualMode(e,n){const t='\n <div class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n ';this.createModal(`\n <div class="glide-content glide-dual-mode">\n <div class="glide-dual-container">\n <div class="glide-dual-item">\n <div class="glide-os-logo">\n ${this.iconApple}\n <span>iOS</span>\n </div>\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(e.iosQRCode)}" alt="iOS QR" class="glide-qr-img" />\n ${t}\n </div>\n </div>\n <div class="glide-dual-separator">\n <div class="glide-separator-line"></div>\n <span class="glide-separator-text">or</span>\n <div class="glide-separator-line"></div>\n </div>\n <div class="glide-dual-item">\n <div class="glide-os-logo">\n ${this.iconAndroid}\n <span>Android</span>\n </div>\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(e.androidQRCode||e.iosQRCode)}" alt="Android QR" class="glide-qr-img" />\n ${t}\n </div>\n </div>\n </div>\n </div>\n `,"glide-modal-wide",!0),this.setupHelpInteraction()}renderPreStepMode(e,n){this.currentStep="os-choice";const t=`\n <div class="glide-pre-step-container">\n <button class="glide-os-choice-btn" id="glide-btn-ios">\n ${this.iconApple}\n <span>iOS</span>\n </button>\n <button class="glide-os-choice-btn" id="glide-btn-android">\n ${this.iconAndroid}\n <span>Android</span>\n </button>\n </div>\n `;this.createModal(t,"",!1),this.setupPreStepListeners(),this.show()}setupPreStepListeners(){this.container&&(this.container.querySelector("#glide-btn-ios")?.addEventListener("click",()=>{this.currentStep="ios-qr",this.updatePreStepUI()}),this.container.querySelector("#glide-btn-android")?.addEventListener("click",()=>{this.currentStep="android-qr",this.updatePreStepUI()}))}updatePreStepUI(){if(!this.container)return;let e="";if("os-choice"===this.currentStep)e=`\n <div class="glide-pre-step-container">\n <button class="glide-os-choice-btn" id="glide-btn-ios">\n ${this.iconApple}\n <span>iOS</span>\n </button>\n <button class="glide-os-choice-btn" id="glide-btn-android">\n ${this.iconAndroid}\n <span>Android</span>\n </button>\n </div>\n `,this.createModal(e,"",!1),this.setupPreStepListeners();else if("ios-qr"===this.currentStep){const n="object"==typeof this.qrCodeData&&this.qrCodeData?.iosQRCode?this.qrCodeData.iosQRCode:this.qrCodeData;e=`\n <div class="glide-content">\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(n)}" alt="QR Code" class="glide-qr-img" />\n \n \x3c!-- Animation Overlay --\x3e\n <div id="glide-phone-overlay" class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n </div>\n </div>\n `,this.createModal(e,"",!0,!0),this.setupBackButton(),this.setupHelpInteraction()}else if("android-qr"===this.currentStep){const n="object"==typeof this.qrCodeData&&this.qrCodeData?.androidQRCode?this.qrCodeData.androidQRCode:"object"==typeof this.qrCodeData&&this.qrCodeData?.iosQRCode?this.qrCodeData.iosQRCode:this.qrCodeData;e=`\n <div class="glide-content">\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(n)}" alt="QR Code" class="glide-qr-img" />\n \n \x3c!-- Animation Overlay --\x3e\n <div id="glide-phone-overlay" class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n </div>\n </div>\n `,this.createModal(e,"",!0,!0),this.setupBackButton(),this.setupHelpInteraction()}}setupBackButton(){this.container&&this.container.querySelector("#glide-back-btn")?.addEventListener("click",()=>{this.currentStep="os-choice",this.updatePreStepUI()})}createModal(e,n="",t=!1,i=!1){this.isClosing&&(this.isClosing=!1,this.cleanup()),this.container?(this.container.className=`glide-modal ${n}`,this.shouldUseDarkMode()&&this.container.classList.add("dark")):(this.backdrop=document.createElement("div"),this.backdrop.className="glide-backdrop",this.backdrop.id="glide-backdrop",this.container=document.createElement("div"),this.container.className=`glide-modal ${n}`,this.container.id="glide-modal",this.shouldUseDarkMode()&&this.container.classList.add("dark"),this.isOpen&&(document.body.appendChild(this.backdrop),document.body.appendChild(this.container))),this.container.innerHTML=`\n ${i?`\n <button class="glide-btn glide-btn-back" id="glide-back-btn" aria-label="Back">\n ${this.iconBack}\n </button>\n `:""}\n ${!1!==this.options?.showCloseButton?'\n <button class="glide-btn glide-btn-close" id="glide-close-btn" aria-label="Close">\n <svg class="glide-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n ':""}\n <h2 class="glide-title">${this.options?.title||"Scan to Verify"}</h2>\n <div id="glide-modal-content">${e}</div>\n <p class="glide-status" id="glide-status">${this.options?.description||""}</p>\n ${t?'\n <button class="glide-btn glide-btn-help" id="glide-help-btn">?</button>\n ':""}\n `,this.injectStyles();const o=this.container.querySelector("#glide-close-btn");o&&o.addEventListener("click",()=>{this.closeCallback?.(),this.close()}),this.backdrop&&(this.backdrop.onclick=e=>{e.target===this.backdrop&&!1!==this.options?.closeOnBackdropClick&&(this.closeCallback?.(),this.close())})}setupHelpInteraction(){const e=this.container?.querySelector("#glide-help-btn");e&&e.addEventListener("click",()=>{const e=this.container?.querySelectorAll(".glide-phone-animation-overlay");e&&e.forEach(e=>{e.classList.remove("playing"),e.offsetWidth,e.classList.add("playing"),setTimeout(()=>{e.classList.remove("playing")},3e3)})})}injectStyles(){if(document.getElementById("glide-modal-styles"))return;const e=document.createElement("style");e.id="glide-modal-styles",e.textContent='\n :root {\n --glide-primary: #007AFF;\n --glide-text: #1d1d1f;\n --glide-bg-light: rgba(255, 255, 255, 0.6);\n --glide-bg-dark: rgba(30, 30, 30, 0.6);\n --glide-phone-border: #000000; /* High Contrast Black */\n \n /* Button sizes */\n --glide-btn-size: 28px;\n --glide-help-btn-size: 24px;\n --glide-toggle-icon-size: 14px;\n --glide-dual-icon-size: 18px;\n }\n\n #glide-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.2);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n z-index: 9998;\n opacity: 0;\n transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n #glide-modal {\n position: fixed;\n top: 20px;\n left: 50%;\n transform: translateX(-50%) scale(0.94);\n background: var(--glide-bg-light);\n backdrop-filter: blur(24px) saturate(180%);\n -webkit-backdrop-filter: blur(24px) saturate(180%);\n border-radius: 24px;\n padding: 32px;\n width: 360px;\n max-width: 90%;\n box-shadow: \n 0 20px 40px rgba(0,0,0,0.2),\n 0 0 0 1px rgba(255,255,255,0.6) inset,\n 0 0 0 1px rgba(0,0,0,0.05);\n z-index: 9999;\n opacity: 0;\n transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;\n text-align: center;\n color: var(--glide-text);\n }\n \n #glide-modal.glide-modal-wide {\n width: 600px;\n max-width: 95vw;\n }\n\n #glide-modal.dark {\n background: var(--glide-bg-dark);\n color: white;\n box-shadow: \n 0 20px 40px rgba(0,0,0,0.4),\n 0 0 0 1px rgba(255,255,255,0.15) inset,\n 0 0 0 1px rgba(0,0,0,0.5);\n --glide-phone-border: #ffffff; /* High Contrast White */\n }\n\n #glide-modal .glide-btn-close {\n position: absolute;\n top: 16px;\n right: 16px;\n width: var(--glide-btn-size);\n height: var(--glide-btn-size);\n min-width: var(--glide-btn-size);\n min-height: var(--glide-btn-size);\n max-width: var(--glide-btn-size);\n max-height: var(--glide-btn-size);\n background: rgba(118, 118, 128, 0.12);\n border: none;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: rgba(0,0,0,0.5);\n transition: background 0.2s;\n padding: 0;\n z-index: 20;\n box-sizing: border-box;\n flex-shrink: 0;\n }\n\n #glide-modal.dark .glide-btn-close {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255,255,255,0.5);\n }\n\n #glide-modal .glide-btn-close:hover {\n background: rgba(118, 118, 128, 0.2);\n }\n \n #glide-modal.dark .glide-btn-close:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n\n .glide-title {\n margin: 0 0 8px 0;\n font-size: 22px;\n font-weight: 600;\n letter-spacing: -0.01em;\n }\n \n .glide-status {\n margin: 12px 0 0 0;\n font-size: 13px;\n color: rgba(0,0,0,0.5);\n text-align: center;\n min-height: 18px;\n }\n \n .glide-status:empty {\n display: none;\n }\n \n #glide-modal.dark .glide-status {\n color: rgba(255,255,255,0.5);\n }\n \n .glide-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n position: relative;\n }\n \n /* --- Sliding Toggle Switch --- */\n #glide-toggle {\n background: rgba(118, 118, 128, 0.12);\n padding: 2px;\n border-radius: 8px;\n display: inline-flex;\n margin-bottom: 24px;\n margin-top: 16px;\n position: relative;\n height: 32px;\n width: 200px;\n box-sizing: border-box;\n }\n\n #glide-modal.dark #glide-toggle {\n background: rgba(118, 118, 128, 0.24);\n }\n \n /* The sliding background */\n .glide-toggle-slider {\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(50% - 2px);\n height: calc(100% - 4px);\n background: white;\n border-radius: 6px;\n box-shadow: 0 3px 8px rgba(0,0,0,0.12), 0 3px 1px rgba(0,0,0,0.04);\n transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n z-index: 0;\n }\n \n #glide-modal.dark .glide-toggle-slider {\n background: #636366;\n }\n \n /* Move slider for Android */\n #glide-toggle[data-active="android"] .glide-toggle-slider {\n transform: translateX(100%);\n }\n\n .glide-toggle-btn {\n flex: 1;\n background: none;\n border: none;\n padding: 0;\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n color: inherit;\n cursor: pointer;\n position: relative;\n z-index: 1;\n transition: color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: auto;\n height: auto;\n min-width: auto;\n border-radius: 0;\n }\n \n #glide-modal .glide-toggle-btn .glide-icon-os,\n #glide-modal .glide-toggle-btn svg {\n width: var(--glide-toggle-icon-size);\n height: var(--glide-toggle-icon-size);\n flex-shrink: 0;\n margin: 0;\n padding: 0;\n }\n \n .glide-toggle-btn span {\n margin: 0;\n padding: 0;\n line-height: 1;\n }\n \n #glide-modal.dark .glide-toggle-btn {\n color: rgba(255,255,255,0.6);\n }\n \n #glide-toggle[data-active="ios"] .glide-toggle-btn[data-platform="ios"],\n #glide-toggle[data-active="android"] .glide-toggle-btn[data-platform="android"] {\n color: #1d1d1f;\n }\n \n #glide-modal.dark #glide-toggle[data-active="ios"] .glide-toggle-btn[data-platform="ios"],\n #glide-modal.dark #glide-toggle[data-active="android"] .glide-toggle-btn[data-platform="android"] {\n color: white;\n }\n\n /* QR Area */\n .glide-qr-area {\n position: relative;\n margin: 0 auto;\n }\n\n .glide-qr-img {\n width: 200px;\n height: 200px;\n object-fit: contain;\n display: block;\n border-radius: 16px;\n }\n \n /* Dual Mode QR Area - no extra padding, same as single mode */\n .glide-dual-mode .glide-qr-area {\n background: transparent;\n padding: 0;\n }\n \n .glide-dual-mode .glide-qr-img {\n width: 180px;\n height: 180px;\n border-radius: 16px;\n }\n \n /* --- Help Icon & Interaction --- */\n .glide-btn-help {\n position: absolute;\n bottom: 20px;\n right: 20px;\n width: var(--glide-help-btn-size);\n height: var(--glide-help-btn-size);\n min-width: var(--glide-help-btn-size);\n min-height: var(--glide-help-btn-size);\n max-width: var(--glide-help-btn-size);\n max-height: var(--glide-help-btn-size);\n border-radius: 50%;\n border: 1.5px solid rgba(0,0,0,0.2);\n color: rgba(0,0,0,0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;\n font-size: 14px;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n transition: all 0.2s;\n background: transparent;\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n z-index: 10;\n }\n \n #glide-modal.dark .glide-btn-help {\n border-color: rgba(255,255,255,0.3);\n color: rgba(255,255,255,0.5);\n }\n\n .glide-btn-help:hover {\n border-color: var(--glide-primary);\n color: var(--glide-primary);\n background: rgba(0, 122, 255, 0.1);\n }\n \n /* Tooltip */\n .glide-btn-help::after {\n content: "Need help?";\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%) translateY(-8px);\n background: rgba(0,0,0,0.8);\n color: white;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 11px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n }\n \n .glide-btn-help:hover::after {\n opacity: 1;\n }\n\n /* --- Outlined Phone Animation --- */\n .glide-phone-animation-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.3s;\n border-radius: 16px;\n background: rgba(255,255,255,0.8);\n }\n \n #glide-modal.dark .glide-phone-animation-overlay {\n background: rgba(0,0,0,0.6);\n }\n \n .glide-phone-animation-overlay.playing {\n opacity: 1;\n }\n\n .glide-outlined-phone {\n width: 100px;\n height: 180px;\n border: 4px solid var(--glide-phone-border);\n border-radius: 16px;\n position: relative;\n background: transparent;\n box-shadow: 0 10px 30px rgba(0,0,0,0.2);\n transform: translateY(20px);\n }\n \n /* Notch */\n .glide-outlined-phone::before {\n content: \'\';\n position: absolute;\n top: -1px;\n left: 50%;\n transform: translateX(-50%);\n width: 40%;\n height: 12px;\n background: var(--glide-phone-border);\n border-bottom-left-radius: 8px;\n border-bottom-right-radius: 8px;\n }\n \n /* Scanning Line */\n .glide-scan-line {\n position: absolute;\n top: 10%;\n left: 5%;\n width: 90%;\n height: 2px;\n background: var(--glide-primary);\n box-shadow: 0 0 8px var(--glide-primary);\n opacity: 0;\n }\n \n /* Animation Keyframes */\n @keyframes glide-scan-motion {\n 0% { top: 10%; opacity: 0; }\n 10% { opacity: 1; }\n 90% { opacity: 1; }\n 100% { top: 90%; opacity: 0; }\n }\n \n .glide-phone-animation-overlay.playing .glide-outlined-phone {\n animation: glide-phone-appear 3s ease-in-out forwards;\n }\n \n .glide-phone-animation-overlay.playing .glide-scan-line {\n animation: glide-scan-motion 2s ease-in-out 0.5s infinite;\n }\n \n @keyframes glide-phone-appear {\n 0% { transform: translateY(20px); opacity: 0; }\n 10% { transform: translateY(0); opacity: 1; }\n 90% { transform: translateY(0); opacity: 1; }\n 100% { transform: translateY(20px); opacity: 0; }\n }\n \n /* Dual Mode */\n .glide-dual-container {\n display: flex;\n justify-content: center;\n align-items: stretch;\n gap: 32px;\n margin-top: 20px;\n }\n \n .glide-dual-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n \n .glide-os-logo {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n margin-bottom: 12px;\n font-size: 15px;\n color: inherit;\n }\n \n /* Dual mode OS logo - aligned icons with text, spacing to QR */\n .glide-dual-mode .glide-os-logo {\n margin-bottom: 12px; /* Space between label and QR code */\n }\n \n #glide-modal .glide-dual-mode .glide-os-logo .glide-icon-os,\n #glide-modal .glide-dual-mode .glide-os-logo svg {\n width: var(--glide-dual-icon-size);\n height: var(--glide-dual-icon-size);\n margin: 0;\n padding: 0;\n flex-shrink: 0;\n }\n \n .glide-dual-mode .glide-os-logo span {\n margin: 0;\n padding: 0;\n line-height: 1;\n }\n \n .glide-os-logo svg {\n width: 20px;\n height: 20px;\n opacity: 0.8;\n }\n \n /* Dual Mode Separator - aligned to QR codes only */\n .glide-dual-separator {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n align-self: stretch;\n /* Offset for OS label (18px icon + 12px margin = ~30px) */\n margin-top: 30px;\n padding: 20px 0;\n }\n \n .glide-separator-line {\n width: 1px;\n flex: 1;\n background: linear-gradient(to bottom, transparent, rgba(128,128,128,0.3), transparent);\n }\n \n .glide-separator-text {\n padding: 8px 0;\n font-size: 11px;\n font-weight: 500;\n color: rgba(128,128,128,0.5);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n \n #glide-modal.dark .glide-separator-line {\n background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.2), transparent);\n }\n \n #glide-modal.dark .glide-separator-text {\n color: rgba(255,255,255,0.4);\n }\n \n /* Pre-Step */\n .glide-pre-step-container {\n display: flex;\n gap: 20px;\n justify-content: center;\n margin: 24px 0;\n }\n \n .glide-os-choice-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 140px;\n height: 140px;\n border: 1px solid rgba(0,0,0,0.08);\n border-radius: 20px;\n background: rgba(255,255,255,0.4);\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n position: relative;\n overflow: hidden;\n font-size: 14px;\n color: inherit;\n }\n \n #glide-modal.dark .glide-os-choice-btn {\n background: rgba(255,255,255,0.05);\n border-color: rgba(255,255,255,0.1);\n color: white;\n }\n \n .glide-os-choice-btn:hover {\n background: rgba(255,255,255,0.9);\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.04);\n border-color: var(--glide-primary);\n }\n \n #glide-modal.dark .glide-os-choice-btn:hover {\n background: rgba(255,255,255,0.15);\n box-shadow: 0 12px 24px rgba(0,0,0,0.3);\n border-color: var(--glide-primary);\n }\n \n .glide-icon-os {\n width: 40px;\n height: 40px;\n margin-bottom: 12px;\n transition: transform 0.3s;\n fill: currentColor;\n }\n \n .glide-os-choice-btn:hover .glide-icon-os {\n transform: scale(1.1);\n }\n \n #glide-modal .glide-btn-back {\n position: absolute;\n top: 16px;\n left: 16px;\n width: var(--glide-btn-size);\n height: var(--glide-btn-size);\n min-width: var(--glide-btn-size);\n min-height: var(--glide-btn-size);\n max-width: var(--glide-btn-size);\n max-height: var(--glide-btn-size);\n background: rgba(118, 118, 128, 0.12);\n border: none;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: rgba(0,0,0,0.5);\n transition: background 0.2s;\n z-index: 20;\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n flex-shrink: 0;\n }\n \n #glide-modal.dark .glide-btn-back {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255,255,255,0.5);\n }\n\n .glide-btn-back:hover {\n background: rgba(118, 118, 128, 0.2);\n }\n \n #glide-modal.dark .glide-btn-back:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n \n .glide-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid rgba(0,0,0,0.1);\n border-top-color: var(--glide-primary);\n border-radius: 50%;\n animation: glide-spin 1s linear infinite;\n margin: 40px auto;\n }\n \n #glide-modal.dark .glide-spinner {\n border-color: rgba(255,255,255,0.1);\n border-top-color: var(--glide-primary);\n }\n \n @keyframes glide-spin {\n to { transform: rotate(360deg); }\n }\n ',document.head.appendChild(e)}show(){this.container&&this.backdrop&&!this.isOpen?(document.body.appendChild(this.backdrop),document.body.appendChild(this.container),this.lockBodyScroll(),document.addEventListener("keydown",this.handleEscapeKey),requestAnimationFrame(()=>{this.backdrop&&this.container&&(this.backdrop.style.opacity="1",this.container.style.opacity="1",this.container.style.transform="translateX(-50%) scale(1)")}),this.isOpen=!0):this.isOpen&&this.container&&this.backdrop&&(document.removeEventListener("keydown",this.handleEscapeKey),document.addEventListener("keydown",this.handleEscapeKey))}setupPlatformToggles(){const e=this.container?.querySelector("#glide-toggle"),n=this.container?.querySelectorAll(".glide-toggle-btn"),t=this.container?.querySelector("#glide-qr-img"),i=this.container?.querySelector("#glide-platform-message");n&&t&&n.forEach(o=>{o.addEventListener("click",o=>{const r=o.currentTarget,a=r.getAttribute("data-platform");e&&a&&e.setAttribute("data-active",a),n.forEach(e=>e.classList.remove("active")),r.classList.add("active"),"ios"===a?(t.src=t.getAttribute("data-ios")||"",i&&(i.textContent="Scan with your iPhone camera")):"android"===a&&(t.src=t.getAttribute("data-android")||"",i&&(i.textContent="Scan with your Android camera"))})})}lockBodyScroll(){this.originalBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden"}unlockBodyScroll(){document.body.style.overflow=this.originalBodyOverflow}close(){this.container&&this.backdrop&&this.isOpen&&(this.isClosing=!0,document.removeEventListener("keydown",this.handleEscapeKey),this.backdrop.style.opacity="0",this.container.style.opacity="0",this.container.style.transform="translateX(-50%) scale(0.94)",this.closeCallback=void 0,setTimeout(()=>{this.isClosing&&(this.cleanup(),this.isOpen=!1,this.isClosing=!1)},400))}cleanup(){this.container?.remove(),this.backdrop?.remove(),this.container=null,this.backdrop=null,this.unlockBodyScroll()}isModalOpen(){return this.isOpen}}function x(e){const{data:n}=e;if(n.ios_qr_image)return{iosQRCode:n.ios_qr_image,androidQRCode:n.android_qr_image||n.ios_qr_image};if(n.qr_code_image)return n.qr_code_image;throw new Error("No QR code data available")}class w{constructor(){this.logs=[],this.container=null,this.logsContainer=null,this.floatingToggle=null,this.isAtBottom=!0,this.isVisible=!0,this.originalConsole={log:console.log,error:console.error,warn:console.warn,debug:console.debug,info:console.info},this.interceptConsole(),this.createUI()}static init(){return w.instance||(w.instance=new w),w.instance}static destroy(){w.instance&&(w.instance.cleanup(),w.instance=null)}interceptConsole(){["log","error","warn","debug","info"].forEach(e=>{const n=this.originalConsole[e];console[e]=(...t)=>{n.apply(console,t),this.addLog(e,t)}})}addLog(e,n){const t=(new Date).toTimeString().split(" ")[0],i=n.map(e=>{if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return"[Object]"}return String(e)}).join(" "),o={log:"#abb2bf",error:"#e06c75",warn:"#e5c07b",info:"#61afef",debug:"#5c6370"},r=`\n <div style="margin: 3px 0; font-family: 'SF Mono', Menlo, Monaco, monospace; font-size: 11px; color: ${o[e]||"#abb2bf"}; line-height: 1.5;">\n <span style="color: #5c6370; font-size: 10px;">${t}</span>\n <span style="background: ${{log:"#3c3c3c",error:"rgba(224, 108, 117, 0.2)",warn:"rgba(229, 192, 123, 0.2)",info:"rgba(97, 175, 239, 0.2)",debug:"#2d2d2d"}[e]}; color: ${o[e]}; padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 500; text-transform: uppercase; margin: 0 6px;">${e}</span>\n <span style="white-space: pre-wrap; word-break: break-all;">${this.escapeHtml(i)}</span>\n </div>\n `;this.logs.push(r),this.logs.length>500&&this.logs.shift(),this.updateDisplay()}updateDisplay(){this.logsContainer&&this.isVisible&&(this.isAtBottom=this.logsContainer.scrollHeight-this.logsContainer.scrollTop<=this.logsContainer.clientHeight+50,this.logsContainer.innerHTML=this.logs.join(""),this.isAtBottom&&(this.logsContainer.scrollTop=this.logsContainer.scrollHeight))}createUI(){const e=document.createElement("style");e.textContent="\n #mobile-debug-console {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n height: 45vh;\n background: #1e1e1e;\n z-index: 999999;\n display: flex;\n flex-direction: column;\n font-family: 'SF Mono', Menlo, Monaco, 'Courier New', monospace;\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n border-top: 1px solid #3c3c3c;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.4);\n }\n \n #mobile-debug-console.hidden {\n transform: translateY(100%);\n }\n \n #debug-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #2d2d2d;\n border-bottom: 1px solid #3c3c3c;\n min-height: 36px;\n }\n \n #debug-title {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #9da5b4;\n font-size: 12px;\n font-weight: 500;\n letter-spacing: 0.3px;\n }\n \n #debug-title svg {\n width: 14px;\n height: 14px;\n opacity: 0.8;\n }\n \n /* Traffic light buttons - using ID for specificity */\n #mobile-debug-console .debug-traffic-lights {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n \n #mobile-debug-console button.debug-traffic-btn {\n width: 16px;\n height: 16px;\n min-width: 16px;\n min-height: 16px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n font-size: 0;\n line-height: 1;\n }\n \n #mobile-debug-console .debug-traffic-btn svg {\n width: 8px;\n height: 8px;\n }\n \n #mobile-debug-console .debug-traffic-btn.close {\n background: #ff5f57;\n }\n \n #mobile-debug-console .debug-traffic-btn.close svg {\n stroke: #820005;\n stroke-width: 2;\n }\n \n #mobile-debug-console .debug-traffic-btn.clear {\n background: #febc2e;\n }\n \n #mobile-debug-console .debug-traffic-btn.minimize {\n background: #28c840;\n }\n \n #mobile-debug-console .debug-traffic-btn.minimize svg {\n stroke: #006500;\n stroke-width: 2;\n }\n \n #mobile-debug-console .debug-traffic-btn:active {\n filter: brightness(0.85);\n }\n \n #debug-logs {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n background: #1e1e1e;\n -webkit-overflow-scrolling: touch;\n }\n \n button#debug-floating-toggle {\n position: fixed !important;\n bottom: 20px !important;\n right: 20px !important;\n width: 42px !important;\n height: 42px !important;\n min-width: 42px !important;\n min-height: 42px !important;\n border-radius: 8px !important;\n background: #2d2d2d !important;\n border: 1px solid #3c3c3c !important;\n color: #9da5b4 !important;\n cursor: pointer !important;\n z-index: 999998 !important;\n display: none;\n align-items: center !important;\n justify-content: center !important;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;\n transition: all 0.2s ease !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n \n button#debug-floating-toggle:hover {\n background: #3c3c3c !important;\n color: #fff !important;\n transform: translateY(-2px) !important;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;\n }\n \n button#debug-floating-toggle:active {\n transform: translateY(0) !important;\n }\n \n button#debug-floating-toggle.visible {\n display: flex !important;\n }\n \n button#debug-floating-toggle svg {\n width: 20px !important;\n height: 20px !important;\n }\n ",document.head.appendChild(e);const n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>';this.container=document.createElement("div"),this.container.id="mobile-debug-console",this.isVisible||(this.container.className="hidden");const t=document.createElement("div");t.id="debug-header";const i=document.createElement("div");i.id="debug-title",i.innerHTML=`${n}<span>Mobile Console</span>`;const o=document.createElement("div");o.className="debug-traffic-lights";const r=document.createElement("button");r.className="debug-traffic-btn close",r.title="Close",r.innerHTML='<svg viewBox="0 0 10 10" fill="none"><line x1="2.5" y1="2.5" x2="7.5" y2="7.5" stroke="currentColor"/><line x1="7.5" y1="2.5" x2="2.5" y2="7.5" stroke="currentColor"/></svg>',r.onclick=()=>this.cleanup();const a=document.createElement("button");a.className="debug-traffic-btn clear",a.title="Clear",a.innerHTML='<svg viewBox="0 0 16 16" fill="currentColor"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/><path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/></svg>',a.onclick=()=>this.clear();const s=document.createElement("button");s.className="debug-traffic-btn minimize",s.title="Minimize",s.innerHTML='<svg viewBox="0 0 10 10" fill="none"><path d="M2 3L5 6L8 3" stroke="currentColor" fill="none"/></svg>',s.onclick=()=>this.toggle(),o.appendChild(r),o.appendChild(a),o.appendChild(s),t.appendChild(o),t.appendChild(i),this.logsContainer=document.createElement("div"),this.logsContainer.id="debug-logs",this.logsContainer.addEventListener("scroll",()=>{this.isAtBottom=this.logsContainer.scrollHeight-this.logsContainer.scrollTop<=this.logsContainer.clientHeight+50}),this.container.appendChild(t),this.container.appendChild(this.logsContainer),document.body.appendChild(this.container),this.floatingToggle=document.createElement("button"),this.floatingToggle.id="debug-floating-toggle",this.floatingToggle.innerHTML=n,this.floatingToggle.title="Show Console",this.floatingToggle.onclick=()=>this.toggle(),document.body.appendChild(this.floatingToggle)}escapeHtml(e){const n=document.createElement("div");return n.textContent=e,n.innerHTML}toggle(){this.isVisible=!this.isVisible,this.container&&this.floatingToggle&&(this.isVisible?(this.container.classList.remove("hidden"),this.floatingToggle.classList.remove("visible"),this.updateDisplay()):(this.container.classList.add("hidden"),this.floatingToggle.classList.add("visible")))}clear(){this.logs=[],this.logsContainer&&(this.logsContainer.innerHTML="")}cleanup(){Object.keys(this.originalConsole).forEach(e=>{console[e]=this.originalConsole[e]}),this.container&&this.container.remove(),this.floatingToggle&&this.floatingToggle.remove()}}w.instance=null;class E{constructor(e={}){this.config={...e,endpoints:{prepare:e.endpoints?.prepare||"/api/magic-auth/prepare",process:e.endpoints?.process||"/api/magic-auth/process",polling:e.endpoints?.polling},headers:e.headers,timeout:e.timeout||3e4,pollingInterval:e.pollingInterval||2e3,maxPollingAttempts:e.maxPollingAttempts||30,debug:e.debug||!1,devEnv:e.devEnv},this.http=e.httpClient||function(e={}){const{timeout:n=3e4,headers:t={},dynamicHeaders:i}=e;async function o(e,n){const o={"Content-Type":"application/json"};t.common&&Object.assign(o,t.common);const r=t[e.endpoint];if(r&&"object"==typeof r&&Object.assign(o,r),i){const n=await i(e);Object.assign(o,n)}return n&&Object.assign(o,n),o}async function r(e,n,t,i){const o=new AbortController,r=setTimeout(()=>o.abort(),t),a=i?()=>o.abort():null;i&&a&&i.addEventListener("abort",a);try{return await fetch(e,{...n,signal:o.signal})}catch(e){if(e instanceof Error&&"AbortError"===e.name){if(i?.aborted)throw h(s.CANCELLED,"Request was cancelled");throw h(s.TIMEOUT,"Request timed out")}throw h(s.NETWORK_ERROR,e instanceof Error?e.message:"Network request failed")}finally{clearTimeout(r),i&&a&&i.removeEventListener("abort",a)}}async function a(e){let n;try{n=await e.json()}catch{if(!e.ok)throw h(s.INVALID_RESPONSE,`Request failed with status ${e.status}`);throw h(s.INVALID_RESPONSE,"Failed to parse response")}if(!e.ok)throw function(e){if(e&&"object"==typeof e&&("code"in e||"error"in e)){const n=e,t=n.code||n.error,i=n.message,o=new Error(i||"An error occurred");return o.code=t,o.status=n.status,o.requestId=n.requestId||n.request_id,o.timestamp=n.timestamp,o.details=n.details,o.traceId=n.trace_id||n.traceId,o.spanId=n.span_id||n.spanId,o.service=n.service,n.details&&"object"==typeof n.details&&"retryAfter"in n.details&&(o.retryAfter=n.details.retryAfter),o}if(e&&"object"==typeof e&&"status"in e){const n=e,t=n.status,i=new Error(n.message||`Request failed with status ${t}`);return i.code=`HTTP_${t}`,i.status=t,i}const n=new Error("An unexpected error occurred");return n.code="UNKNOWN_ERROR",n}("object"!=typeof n||null===n||Array.isArray(n)?{status:e.status,rawResponse:n}:{...n,status:e.status});return n}function l(e){return e.includes("/prepare")?"prepare":e.includes("/process")||e.includes("/get-phone")||e.includes("/verify-phone")?"process":e.includes("/status")?"polling":"prepare"}return{async post(e,t,i){const s=l(e),d=await o({endpoint:s,method:"POST"},i?.headers);return a(await r(e,{method:"POST",headers:d,body:JSON.stringify(t)},i?.timeout||n,i?.signal))},async get(e,t){const i=l(e),s=await o({endpoint:i,method:"GET"},t?.headers);return delete s["Content-Type"],a(await r(e,{method:"GET",headers:s},t?.timeout||n,t?.signal))}}}({timeout:this.config.timeout,headers:e.headers,dynamicHeaders:e.dynamicHeaders}),this.logger=e.logger||(this.config.debug?function(e={}){const{debug:n=!1,prefix:t="[PhoneAuth]"}=e;function i(e,n){const i=`${t} ${e}`;return void 0!==n?[i,f(n)]:[i]}return{debug(e,t){if(n){const n=i(e,t);console.debug(...n)}},info(e,n){const t=i(e,n);console.info(...t)},warn(e,n){const t=i(e,n);console.warn(...t)},error(e,n){const t=i(e,n);console.error(...t)}}}({debug:!0}):{debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}}),this.logger.debug("PhoneAuthClient initialized",{endpoints:this.config.endpoints,timeout:this.config.timeout,...e.devEnv&&{devEnv:e.devEnv}}),e.devtools?.showMobileConsole&&"undefined"!=typeof window&&(w.init(),this.logger.info("Mobile debug console enabled"))}async authenticate(e,n){const i=await this.prepare(e),o=await this.invokeSecurePrompt(i,n),r=await o.credential,a=i.session.use_case||i.session.metadata?.use_case||e.use_case;if(!a)throw h(s.INVALID_RESPONSE,"Could not determine use_case from session or request");return a===t.VERIFY_PHONE_NUMBER?this.verifyPhoneNumber(r,i.session):this.getPhoneNumber(r,i.session)}async prepare(e){if(this.logger.debug("Preparing authentication",{use_case:e.use_case}),e.phone_number){const n=r(e.phone_number);if(!n.valid)throw h(s.INVALID_PHONE_NUMBER,n.error)}if(e.plmn){const n=a(e.plmn);if(!n.valid)throw h(s.INVALID_PLMN,n.error)}if(!e.use_case&&!e.options?.parent_session_id)throw h(s.MISSING_PARAMETERS,"use_case is required");if(e.use_case){const r=(n=e.use_case,i=e.phone_number,o=!!e.options?.parent_session_id,n!==t.VERIFY_PHONE_NUMBER||i||o?{valid:!0}:{valid:!1,error:"Phone number is required for VerifyPhoneNumber use case"});if(!r.valid)throw h(s.MISSING_PARAMETERS,r.error)}var n,i,o;const l={...e,id:e.id||this.generateRequestId(),client_info:e.client_info||{user_agent:navigator.userAgent,platform:navigator.platform}};try{const e=await this.http.post(this.config.endpoints.prepare,l);return this.logger.debug("Prepare successful",{strategy:e.authentication_strategy,sessionKey:e.session.session_key}),e}catch(e){throw this.logger.error("Prepare failed",e),e}}async invokeSecurePrompt(e,n){const{authentication_strategy:t,session:o,data:r}=e;switch(this.logger.debug("Invoking secure prompt",{strategy:t}),t){case i.TS43:return this.handleTS43(r,o);case i.LINK:return this.handleLink(r,o,n);case i.DESKTOP:return this.handleDesktop(r,o,n);default:throw h(s.UNSUPPORTED_STRATEGY,`Unknown strategy: ${t}`)}}async getPhoneNumber(e,n){this.logger.debug("Getting phone number");const i={session:n,credential:e,use_case:t.GET_PHONE_NUMBER};try{const e=await this.http.post(this.config.endpoints.process,i);return this.logger.info("Phone number retrieved"),e}catch(e){throw this.logger.error("Get phone number failed",e),e}}async verifyPhoneNumber(e,n){this.logger.debug("Verifying phone number");const i={session:n,credential:e,use_case:t.VERIFY_PHONE_NUMBER};try{const e=await this.http.post(this.config.endpoints.process,i);return this.logger.info("Phone number verified",{verified:e.verified}),e}catch(e){throw this.logger.error("Verify phone number failed",e),e}}isSupported(){return"undefined"!=typeof window&&"DigitalCredential"in window}getBrowserSupportInfo(){if("undefined"==typeof window)return{supported:!1,browser:"unknown",message:"Not in browser"};const e=navigator.userAgent,n=/Chrome/.test(e)&&/Google Inc/.test(navigator.vendor),t=/Edg\//.test(e);return this.isSupported()?{supported:!0,browser:n?"Chrome":t?"Edge":"Other"}:{supported:!1,browser:n?"Chrome":t?"Edge":"Other",message:"Enable chrome://flags/#web-identity-digital-credentials"}}async handleTS43(e,n){if(!this.isSupported())throw h(s.BROWSER_NOT_SUPPORTED,"Digital Credentials API not available");const t={digital:{requests:[{protocol:e.protocol,data:e.data}]}};return this.logger.debug("Invoking Digital Credentials API"),{credential:(async()=>{try{const e=await navigator.credentials.get(t);if(!e?.data?.vp_token)throw h(s.INVALID_RESPONSE,"No credential returned from Digital Credentials API");const n=e.data.vp_token,i="string"==typeof n?n:Object.values(n)[0],o=Array.isArray(i)?i[0]:i;if(!o||"string"==typeof o&&""===o.trim())throw h(s.INVALID_RESPONSE,"Empty credential returned from Digital Credentials API");return"undefined"!=typeof navigator&&navigator.vibrate&&setTimeout(()=>{try{navigator.vibrate([80,50,80])}catch(e){}},200),o}catch(e){if(d(e))throw e;const n=e;if("NotAllowedError"===n.name||"NetworkError"===n.name&&19===n.code)throw h(s.USER_CANCELLED,"User cancelled authentication");if("NotSupportedError"===n.name)throw h(s.BROWSER_NOT_SUPPORTED,"Browser not supported");throw h(s.NETWORK_ERROR,n.message||"Credential request failed")}})(),cancel:void 0,strategy:i.TS43,session:n}}handleLink(e,n,t){if(!e.url)throw h(s.INVALID_RESPONSE,"Missing link URL");this.logger.debug("Opening App Clip",{url:e.url}),window.location.href=e.url;const o={...this.config.headers?.common,...this.config.headers?.polling};this.config.devEnv&&(o.developer=this.config.devEnv,this.logger.debug("Adding developer header for polling",{devEnv:this.config.devEnv}));const r=v({sessionKey:n.session_key,interval:t?.pollingInterval||this.config.pollingInterval,maxAttempts:t?.maxPollingAttempts||this.config.maxPollingAttempts,pollingEndpoint:t?.pollingEndpoint||this.config.endpoints.polling,statusUrl:e.status_url,logger:this.logger,headers:Object.keys(o).length>0?o:void 0});return{credential:r.start().then(e=>{if("completed"===e.status&&e.credential)return e.credential;throw h(s.VERIFICATION_FAILED,e.message||"Link authentication failed")}),cancel:()=>r.cancel(),strategy:i.LINK,session:n}}handleDesktop(e,n,t){const o=e.data?.session_id||n.session_key;this.logger.debug("Starting desktop authentication",{sessionId:o});const r={...this.config.headers?.common,...this.config.headers?.polling};this.config.devEnv&&(r.developer=this.config.devEnv,this.logger.debug("Adding developer header for polling",{devEnv:this.config.devEnv}));const a=v({sessionKey:o,interval:t?.pollingInterval||this.config.pollingInterval,maxAttempts:t?.maxPollingAttempts||this.config.maxPollingAttempts,pollingEndpoint:t?.pollingEndpoint||this.config.endpoints.polling,statusUrl:e.data?.status_url,logger:this.logger,headers:Object.keys(r).length>0?r:void 0});let l=null;if(!t?.preventDefaultUI)try{const n=x(e);l=new y(t?.modalOptions),l.showQRCode(n,t?.modalOptions?.description||"Scan with your phone camera"),l.setCloseCallback(()=>{this.logger.debug("Modal closed by user, cancelling authentication"),a.cancel()}),this.logger.debug("Desktop modal displayed")}catch(e){this.logger.warn("Failed to show modal, continuing with polling only",e)}return{credential:a.start().then(e=>{if(l&&l.close(),"completed"===e.status&&e.credential)return e.credential;throw h(s.VERIFICATION_FAILED,e.message||"Desktop authentication failed")}).catch(e=>{throw l&&l.close(),e}),cancel:()=>{a.cancel(),l&&l.close()},strategy:i.DESKTOP,session:n}}generateRequestId(){return`web-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}}function k(e){return null!==e&&"object"==typeof e&&"credential"in e&&"strategy"in e&&"session"in e}function C(e){return null!==e&&"object"==typeof e&&"credential"in e&&"authenticated"in e&&"session"in e}function S(e){return e.strategy===i.TS43}function A(e){return e.strategy===i.LINK}function R(e){return e.strategy===i.DESKTOP}function _(e){return void 0!==e.cancel}function I(e){return null!==e&&"object"==typeof e&&"protocol"in e&&"data"in e&&"object"==typeof e.data&&"dcql_query"in e.data}function N(e){return null!==e&&"object"==typeof e&&"url"in e&&"string"==typeof e.url}function O(e){return null!==e&&"object"==typeof e&&"data"in e&&"object"==typeof e.data&&null!==e.data&&!("dcql_query"in e.data)}function T(e){return!("verified"in e)}function P(e){return"verified"in e}function L(e){return null!==e&&"object"==typeof e&&"code"in e&&"message"in e}return n})());
1
+ !function(e,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.GlideWebClientSDK=n():e.GlideWebClientSDK=n()}(this,()=>(()=>{"use strict";var e={d:(n,t)=>{for(var i in t)e.o(t,i)&&!e.o(n,i)&&Object.defineProperty(n,i,{enumerable:!0,get:t[i]})},o:(e,n)=>Object.prototype.hasOwnProperty.call(e,n),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},n={};e.r(n),e.d(n,{AUTHENTICATION_STRATEGY:()=>i,AuthModal:()=>y,ERROR_CODES:()=>s,PhoneAuthClient:()=>E,USE_CASE:()=>t,createAuthError:()=>h,createQRCodeDataFromDesktop:()=>x,getUserMessage:()=>p,isAuthCredential:()=>C,isAuthError:()=>d,isCancellable:()=>_,isClientError:()=>c,isDesktopData:()=>T,isDesktopStrategy:()=>R,isErrorResponse:()=>L,isGetPhoneNumberResponse:()=>O,isInvokeResult:()=>k,isLinkData:()=>N,isLinkStrategy:()=>A,isRetryableError:()=>g,isTS43Data:()=>I,isTS43Strategy:()=>S,isVerifyPhoneNumberResponse:()=>P,validatePhoneNumber:()=>r,validatePlmn:()=>a});const t={GET_PHONE_NUMBER:"GetPhoneNumber",VERIFY_PHONE_NUMBER:"VerifyPhoneNumber"},i={TS43:"ts43",LINK:"link",DESKTOP:"desktop"},o=/^\+[1-9]\d{1,14}$/;function r(e){return e?e.startsWith("+")?e.length<8?{valid:!1,error:"Phone number too short for E.164 format (minimum 8 characters including +)"}:e.length>16?{valid:!1,error:"Phone number too long for E.164 format (maximum 15 digits after +)"}:/^\+\d+$/.test(e)?o.test(e)?{valid:!0}:{valid:!1,error:"Invalid E.164 phone number format"}:{valid:!1,error:"Phone number contains invalid characters. E.164 format only allows + followed by digits"}:{valid:!1,error:"Phone number must be in E.164 format (start with +)"}:{valid:!0}}function a(e){if(!e)return{valid:!0};const{mcc:n,mnc:t}=e;return n&&/^\d{3}$/.test(n)?t&&/^\d{2,3}$/.test(t)?{valid:!0}:{valid:!1,error:"MNC must be 2 or 3 digits"}:{valid:!1,error:"MCC must be exactly 3 digits"}}const s={INVALID_PHONE_NUMBER:"INVALID_PHONE_NUMBER",INVALID_PLMN:"INVALID_PLMN",MISSING_PARAMETERS:"MISSING_PARAMETERS",BROWSER_NOT_SUPPORTED:"BROWSER_NOT_SUPPORTED",UNSUPPORTED_STRATEGY:"UNSUPPORTED_STRATEGY",USER_CANCELLED:"USER_CANCELLED",CANCELLED:"CANCELLED",VERIFICATION_FAILED:"VERIFICATION_FAILED",NETWORK_ERROR:"NETWORK_ERROR",TIMEOUT:"TIMEOUT",INVALID_RESPONSE:"INVALID_RESPONSE"},l={[s.INVALID_PHONE_NUMBER]:"Please enter a valid phone number in E.164 format (e.g., +14155551234).",[s.INVALID_PLMN]:"Invalid carrier information provided.",[s.MISSING_PARAMETERS]:"Required information is missing.",[s.BROWSER_NOT_SUPPORTED]:"Your browser does not support this authentication method. Please use Chrome or Edge with the Digital Credentials flag enabled.",[s.UNSUPPORTED_STRATEGY]:"This authentication strategy is not supported.",[s.USER_CANCELLED]:"Authentication was cancelled.",[s.CANCELLED]:"Authentication was cancelled.",[s.VERIFICATION_FAILED]:"Verification failed. Please try again.",[s.NETWORK_ERROR]:"Network connection failed. Please check your connection and try again.",[s.TIMEOUT]:"Request timed out. Please try again.",[s.INVALID_RESPONSE]:"Invalid response received."};function d(e){return null!==e&&"object"==typeof e&&"code"in e&&"message"in e&&"string"==typeof e.code&&"string"==typeof e.message}function c(e){return Object.values(s).includes(e.code)}function g(e){return e.code===s.NETWORK_ERROR||e.code===s.TIMEOUT}function p(e){return c(e)&&l[e.code]||e.message}function h(e,n,t,i){const o=new Error(n||l[e]||e);if(o.code=e,o.details=t,o.timestamp=(new Date).toISOString(),i){o.cause=i;const e=i;o.browserError={name:i.name,message:i.message,code:e.code}}return o}const u=/(\+?[1-9]\d{6,14})/g,b=/(eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*)/g,m=/session[_-]?key["']?\s*[:=]\s*["']?([a-zA-Z0-9_-]{20,})["']?/gi;function f(e){if(null==e)return e;if("string"==typeof e){let n=e;return n=n.replace(u,e=>e.length<8?e:e.slice(0,2)+"***"+e.slice(-4)),n=n.replace(b,"[JWT]"),n=n.replace(m,(e,n)=>e.replace(n,n.slice(0,4)+"***"+n.slice(-4))),n}if(Array.isArray(e))return e.map(f);if("object"==typeof e){const n={};for(const[t,i]of Object.entries(e))["phone_number","phoneNumber","credential","token","password","secret"].some(e=>t.toLowerCase().includes(e.toLowerCase()))?n[t]="string"==typeof i?"[REDACTED]":i:n[t]=f(i);return n}return e}function v(e){const{sessionKey:n,interval:t=2e3,maxAttempts:i=30,pollingEndpoint:o,statusUrl:r,logger:a,headers:l}=e;let d,c,g=0,p=!1,u=!1;function b(){u=!1,d&&(clearInterval(d),d=void 0)}return{start:function(){return new Promise((e,s)=>{c=s,u=!0,g=0;const h=async()=>{if(u&&!p){if(g>=i)return b(),a?.warn("Polling timeout reached",{attempts:g,maxAttempts:i}),void e({status:"expired",message:"Authentication timeout"});try{const t=o?(a?.debug("Using developer config endpoint for polling",{pollingEndpoint:o}),`${o}/${n}`):r?(a?.debug("Using backend status_url for polling",{statusUrl:r}),r):(a?.debug("Using prod fallback for status polling"),`https://api.glideidentity.app/public/status/${n}`);a?.debug("Polling status",{url:t,attempt:g+1,maxAttempts:i});const s=await fetch(t,{method:"GET",headers:{Accept:"application/json",...l}});if(200===s.status){const t=await s.json();if("completed"===t.status){b(),a?.info("Authentication completed");const i=t.credential||n;return void e({status:"completed",credential:i,session:t.session||{session_key:n}})}g++}else if(410===s.status){b();const n=await s.json().catch(()=>({}));e({status:"expired",message:n.message||"Session expired"})}else if(422===s.status){b();const n=await s.json().catch(()=>({}));e({status:"error",message:n.message||"Authentication failed"})}else 404===s.status?(b(),e({status:"error",message:"Session not found"})):g++}catch(e){a?.debug("Polling error, retrying",{error:e,attempt:g+1}),g++}}};h(),d=setInterval(h,t)})},stop:b,cancel:function(){a?.debug("Polling cancelled"),p=!0,b(),c&&(c(h(s.CANCELLED,"Authentication cancelled")),c=void 0)},isPolling:function(){return void 0!==d},cleanup:function(){b(),p=!1,c=void 0}}}class y{constructor(e){this.container=null,this.backdrop=null,this.isOpen=!1,this.currentStep="os-choice",this.qrCodeData=null,this.statusMessage="",this.originalBodyOverflow="",this.isClosing=!1,this.iconApple='<svg class="glide-icon glide-icon-os" viewBox="0 0 384 512" fill="currentColor"><path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 52.3-11.4 69.5-34.3z"/></svg>',this.iconAndroid='<svg class="glide-icon glide-icon-os" viewBox="0 0 576 512" fill="currentColor"><path d="M420.55,301.93a24,24,0,1,1,24-24,24,24,0,0,1-24,24m-265.1,0a24,24,0,1,1,24-24,24,24,0,0,1-24,24m273.7-144.48,47.94-83a10,10,0,1,0-17.27-10h0l-48.54,84.07a301.25,301.25,0,0,0-246.56,0L116.18,64.45a10,10,0,1,0-17.27,10h0l47.94,83C64.53,202.22,8.24,285.55,0,384H576c-8.24-98.45-64.54-181.78-146.85-226.55"/></svg>',this.iconBack='<svg class="glide-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>',this.options=e||{},this.theme=this.options.theme||"auto",this.handleEscapeKey=this.handleEscapeKey.bind(this)}shouldUseDarkMode(){return"dark"===this.theme||"light"!==this.theme&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches}handleEscapeKey(e){"Escape"===e.key&&this.isOpen&&!1!==this.options?.closeOnEscape&&(this.closeCallback?.(),this.close())}escapeHtml(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}showQRCode(e,n="Scan with your phone camera"){this.qrCodeData=e,this.statusMessage=n;const t=this.options.viewMode||"toggle";if("string"==typeof e)this.renderToggleMode(e,n);else switch(t){case"dual":this.renderDualMode(e,n);break;case"pre-step":this.renderPreStepMode(e,n);break;default:this.renderToggleMode(e,n)}this.show()}updateStatus(e,n=!1){if(this.statusMessage=e,this.container){const t=this.container.querySelector("#glide-status");t&&(t.textContent=e,t.style.color=n?"#ff3b30":"")}}setCloseCallback(e){this.closeCallback=e}renderToggleMode(e,n){let t="",i="";"string"==typeof e?(t=e,i=e):(t=e.iosQRCode,i=e.androidQRCode||e.iosQRCode);const o=`\n <div class="glide-content">\n <div class="glide-toggle" id="glide-toggle" data-active="ios">\n <div class="glide-toggle-slider"></div>\n <button class="glide-btn glide-toggle-btn active" data-platform="ios">${this.iconApple}<span>iOS</span></button>\n <button class="glide-btn glide-toggle-btn" data-platform="android">${this.iconAndroid}<span>Android</span></button>\n </div>\n\n <div class="glide-qr-area">\n <img \n class="glide-qr-img"\n id="glide-qr-img" \n src="${this.escapeHtml(t)}" \n alt="QR Code" \n class="glide-qr-img" \n data-ios="${this.escapeHtml(t)}"\n data-android="${this.escapeHtml(i)}"\n />\n \n \x3c!-- Animation Overlay (Inside QR Area for centering) --\x3e\n <div id="glide-phone-overlay" class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n </div>\n </div>\n `;this.createModal(o,"",!0),this.setupPlatformToggles(),this.setupHelpInteraction()}renderDualMode(e,n){const t='\n <div class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n ';this.createModal(`\n <div class="glide-content glide-dual-mode">\n <div class="glide-dual-container">\n <div class="glide-dual-item">\n <div class="glide-os-logo">\n ${this.iconApple}\n <span>iOS</span>\n </div>\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(e.iosQRCode)}" alt="iOS QR" class="glide-qr-img" />\n ${t}\n </div>\n </div>\n <div class="glide-dual-separator">\n <div class="glide-separator-line"></div>\n <span class="glide-separator-text">or</span>\n <div class="glide-separator-line"></div>\n </div>\n <div class="glide-dual-item">\n <div class="glide-os-logo">\n ${this.iconAndroid}\n <span>Android</span>\n </div>\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(e.androidQRCode||e.iosQRCode)}" alt="Android QR" class="glide-qr-img" />\n ${t}\n </div>\n </div>\n </div>\n </div>\n `,"glide-modal-wide",!0),this.setupHelpInteraction()}renderPreStepMode(e,n){this.currentStep="os-choice";const t=`\n <div class="glide-pre-step-container">\n <button class="glide-os-choice-btn" id="glide-btn-ios">\n ${this.iconApple}\n <span>iOS</span>\n </button>\n <button class="glide-os-choice-btn" id="glide-btn-android">\n ${this.iconAndroid}\n <span>Android</span>\n </button>\n </div>\n `;this.createModal(t,"",!1),this.setupPreStepListeners(),this.show()}setupPreStepListeners(){this.container&&(this.container.querySelector("#glide-btn-ios")?.addEventListener("click",()=>{this.currentStep="ios-qr",this.updatePreStepUI()}),this.container.querySelector("#glide-btn-android")?.addEventListener("click",()=>{this.currentStep="android-qr",this.updatePreStepUI()}))}updatePreStepUI(){if(!this.container)return;let e="";if("os-choice"===this.currentStep)e=`\n <div class="glide-pre-step-container">\n <button class="glide-os-choice-btn" id="glide-btn-ios">\n ${this.iconApple}\n <span>iOS</span>\n </button>\n <button class="glide-os-choice-btn" id="glide-btn-android">\n ${this.iconAndroid}\n <span>Android</span>\n </button>\n </div>\n `,this.createModal(e,"",!1),this.setupPreStepListeners();else if("ios-qr"===this.currentStep){const n="object"==typeof this.qrCodeData&&this.qrCodeData?.iosQRCode?this.qrCodeData.iosQRCode:this.qrCodeData;e=`\n <div class="glide-content">\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(n)}" alt="QR Code" class="glide-qr-img" />\n \n \x3c!-- Animation Overlay --\x3e\n <div id="glide-phone-overlay" class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n </div>\n </div>\n `,this.createModal(e,"",!0,!0),this.setupBackButton(),this.setupHelpInteraction()}else if("android-qr"===this.currentStep){const n="object"==typeof this.qrCodeData&&this.qrCodeData?.androidQRCode?this.qrCodeData.androidQRCode:"object"==typeof this.qrCodeData&&this.qrCodeData?.iosQRCode?this.qrCodeData.iosQRCode:this.qrCodeData;e=`\n <div class="glide-content">\n <div class="glide-qr-area">\n <img src="${this.escapeHtml(n)}" alt="QR Code" class="glide-qr-img" />\n \n \x3c!-- Animation Overlay --\x3e\n <div id="glide-phone-overlay" class="glide-phone-animation-overlay">\n <div class="glide-outlined-phone">\n <div class="glide-scan-line"></div>\n </div>\n </div>\n </div>\n </div>\n `,this.createModal(e,"",!0,!0),this.setupBackButton(),this.setupHelpInteraction()}}setupBackButton(){this.container&&this.container.querySelector("#glide-back-btn")?.addEventListener("click",()=>{this.currentStep="os-choice",this.updatePreStepUI()})}createModal(e,n="",t=!1,i=!1){this.isClosing&&(this.isClosing=!1,this.cleanup()),this.container?(this.container.className=`glide-modal ${n}`,this.shouldUseDarkMode()&&this.container.classList.add("dark")):(this.backdrop=document.createElement("div"),this.backdrop.className="glide-backdrop",this.backdrop.id="glide-backdrop",this.container=document.createElement("div"),this.container.className=`glide-modal ${n}`,this.container.id="glide-modal",this.shouldUseDarkMode()&&this.container.classList.add("dark"),this.isOpen&&(document.body.appendChild(this.backdrop),document.body.appendChild(this.container))),this.container.innerHTML=`\n ${i?`\n <button class="glide-btn glide-btn-back" id="glide-back-btn" aria-label="Back">\n ${this.iconBack}\n </button>\n `:""}\n ${!1!==this.options?.showCloseButton?'\n <button class="glide-btn glide-btn-close" id="glide-close-btn" aria-label="Close">\n <svg class="glide-icon" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">\n <line x1="18" y1="6" x2="6" y2="18"></line>\n <line x1="6" y1="6" x2="18" y2="18"></line>\n </svg>\n </button>\n ':""}\n <h2 class="glide-title">${this.options?.title||"Scan to Verify"}</h2>\n <div id="glide-modal-content">${e}</div>\n <p class="glide-status" id="glide-status">${this.options?.description||""}</p>\n ${t?'\n <button class="glide-btn glide-btn-help" id="glide-help-btn">?</button>\n ':""}\n `,this.injectStyles();const o=this.container.querySelector("#glide-close-btn");o&&o.addEventListener("click",()=>{this.closeCallback?.(),this.close()}),this.backdrop&&(this.backdrop.onclick=e=>{e.target===this.backdrop&&!1!==this.options?.closeOnBackdropClick&&(this.closeCallback?.(),this.close())})}setupHelpInteraction(){const e=this.container?.querySelector("#glide-help-btn");e&&e.addEventListener("click",()=>{const e=this.container?.querySelectorAll(".glide-phone-animation-overlay");e&&e.forEach(e=>{e.classList.remove("playing"),e.offsetWidth,e.classList.add("playing"),setTimeout(()=>{e.classList.remove("playing")},3e3)})})}injectStyles(){if(document.getElementById("glide-modal-styles"))return;const e=document.createElement("style");e.id="glide-modal-styles",e.textContent='\n :root {\n --glide-primary: #007AFF;\n --glide-text: #1d1d1f;\n --glide-bg-light: rgba(255, 255, 255, 0.6);\n --glide-bg-dark: rgba(30, 30, 30, 0.6);\n --glide-phone-border: #000000; /* High Contrast Black */\n \n /* Button sizes */\n --glide-btn-size: 28px;\n --glide-help-btn-size: 24px;\n --glide-toggle-icon-size: 14px;\n --glide-dual-icon-size: 18px;\n }\n\n #glide-backdrop {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.2);\n backdrop-filter: blur(8px);\n -webkit-backdrop-filter: blur(8px);\n z-index: 9998;\n opacity: 0;\n transition: opacity 0.4s cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n #glide-modal {\n position: fixed;\n top: 20px;\n left: 50%;\n transform: translateX(-50%) scale(0.94);\n background: var(--glide-bg-light);\n backdrop-filter: blur(24px) saturate(180%);\n -webkit-backdrop-filter: blur(24px) saturate(180%);\n border-radius: 24px;\n padding: 32px;\n width: 360px;\n max-width: 90%;\n box-shadow: \n 0 20px 40px rgba(0,0,0,0.2),\n 0 0 0 1px rgba(255,255,255,0.6) inset,\n 0 0 0 1px rgba(0,0,0,0.05);\n z-index: 9999;\n opacity: 0;\n transition: opacity 0.4s ease, transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;\n text-align: center;\n color: var(--glide-text);\n }\n \n #glide-modal.glide-modal-wide {\n width: 600px;\n max-width: 95vw;\n }\n\n #glide-modal.dark {\n background: var(--glide-bg-dark);\n color: white;\n box-shadow: \n 0 20px 40px rgba(0,0,0,0.4),\n 0 0 0 1px rgba(255,255,255,0.15) inset,\n 0 0 0 1px rgba(0,0,0,0.5);\n --glide-phone-border: #ffffff; /* High Contrast White */\n }\n\n #glide-modal .glide-btn-close {\n position: absolute;\n top: 16px;\n right: 16px;\n width: var(--glide-btn-size);\n height: var(--glide-btn-size);\n min-width: var(--glide-btn-size);\n min-height: var(--glide-btn-size);\n max-width: var(--glide-btn-size);\n max-height: var(--glide-btn-size);\n background: rgba(118, 118, 128, 0.12);\n border: none;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: rgba(0,0,0,0.5);\n transition: background 0.2s;\n padding: 0;\n z-index: 20;\n box-sizing: border-box;\n flex-shrink: 0;\n }\n\n #glide-modal.dark .glide-btn-close {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255,255,255,0.5);\n }\n\n #glide-modal .glide-btn-close:hover {\n background: rgba(118, 118, 128, 0.2);\n }\n \n #glide-modal.dark .glide-btn-close:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n\n .glide-title {\n margin: 0 0 8px 0;\n font-size: 22px;\n font-weight: 600;\n letter-spacing: -0.01em;\n }\n \n .glide-status {\n margin: 12px 0 0 0;\n font-size: 13px;\n color: rgba(0,0,0,0.5);\n text-align: center;\n min-height: 18px;\n }\n \n .glide-status:empty {\n display: none;\n }\n \n #glide-modal.dark .glide-status {\n color: rgba(255,255,255,0.5);\n }\n \n .glide-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n position: relative;\n }\n \n /* --- Sliding Toggle Switch --- */\n #glide-toggle {\n background: rgba(118, 118, 128, 0.12);\n padding: 2px;\n border-radius: 8px;\n display: inline-flex;\n margin-bottom: 24px;\n margin-top: 16px;\n position: relative;\n height: 32px;\n width: 200px;\n box-sizing: border-box;\n }\n\n #glide-modal.dark #glide-toggle {\n background: rgba(118, 118, 128, 0.24);\n }\n \n /* The sliding background */\n .glide-toggle-slider {\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(50% - 2px);\n height: calc(100% - 4px);\n background: white;\n border-radius: 6px;\n box-shadow: 0 3px 8px rgba(0,0,0,0.12), 0 3px 1px rgba(0,0,0,0.04);\n transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n z-index: 0;\n }\n \n #glide-modal.dark .glide-toggle-slider {\n background: #636366;\n }\n \n /* Move slider for Android */\n #glide-toggle[data-active="android"] .glide-toggle-slider {\n transform: translateX(100%);\n }\n\n .glide-toggle-btn {\n flex: 1;\n background: none;\n border: none;\n padding: 0;\n margin: 0;\n font-size: 13px;\n font-weight: 500;\n color: inherit;\n cursor: pointer;\n position: relative;\n z-index: 1;\n transition: color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n min-height: auto;\n height: auto;\n min-width: auto;\n border-radius: 0;\n }\n \n #glide-modal .glide-toggle-btn .glide-icon-os,\n #glide-modal .glide-toggle-btn svg {\n width: var(--glide-toggle-icon-size);\n height: var(--glide-toggle-icon-size);\n flex-shrink: 0;\n margin: 0;\n padding: 0;\n }\n \n .glide-toggle-btn span {\n margin: 0;\n padding: 0;\n line-height: 1;\n }\n \n #glide-modal.dark .glide-toggle-btn {\n color: rgba(255,255,255,0.6);\n }\n \n #glide-toggle[data-active="ios"] .glide-toggle-btn[data-platform="ios"],\n #glide-toggle[data-active="android"] .glide-toggle-btn[data-platform="android"] {\n color: #1d1d1f;\n }\n \n #glide-modal.dark #glide-toggle[data-active="ios"] .glide-toggle-btn[data-platform="ios"],\n #glide-modal.dark #glide-toggle[data-active="android"] .glide-toggle-btn[data-platform="android"] {\n color: white;\n }\n\n /* QR Area */\n .glide-qr-area {\n position: relative;\n margin: 0 auto;\n }\n\n .glide-qr-img {\n width: 200px;\n height: 200px;\n object-fit: contain;\n display: block;\n border-radius: 16px;\n }\n \n /* Dual Mode QR Area - no extra padding, same as single mode */\n .glide-dual-mode .glide-qr-area {\n background: transparent;\n padding: 0;\n }\n \n .glide-dual-mode .glide-qr-img {\n width: 180px;\n height: 180px;\n border-radius: 16px;\n }\n \n /* --- Help Icon & Interaction --- */\n .glide-btn-help {\n position: absolute;\n bottom: 20px;\n right: 20px;\n width: var(--glide-help-btn-size);\n height: var(--glide-help-btn-size);\n min-width: var(--glide-help-btn-size);\n min-height: var(--glide-help-btn-size);\n max-width: var(--glide-help-btn-size);\n max-height: var(--glide-help-btn-size);\n border-radius: 50%;\n border: 1.5px solid rgba(0,0,0,0.2);\n color: rgba(0,0,0,0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;\n font-size: 14px;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n transition: all 0.2s;\n background: transparent;\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n z-index: 10;\n }\n \n #glide-modal.dark .glide-btn-help {\n border-color: rgba(255,255,255,0.3);\n color: rgba(255,255,255,0.5);\n }\n\n .glide-btn-help:hover {\n border-color: var(--glide-primary);\n color: var(--glide-primary);\n background: rgba(0, 122, 255, 0.1);\n }\n \n /* Tooltip */\n .glide-btn-help::after {\n content: "Need help?";\n position: absolute;\n bottom: 100%;\n left: 50%;\n transform: translateX(-50%) translateY(-8px);\n background: rgba(0,0,0,0.8);\n color: white;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 11px;\n white-space: nowrap;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n }\n \n .glide-btn-help:hover::after {\n opacity: 1;\n }\n\n /* --- Outlined Phone Animation --- */\n .glide-phone-animation-overlay {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n opacity: 0;\n transition: opacity 0.3s;\n border-radius: 16px;\n background: rgba(255,255,255,0.8);\n }\n \n #glide-modal.dark .glide-phone-animation-overlay {\n background: rgba(0,0,0,0.6);\n }\n \n .glide-phone-animation-overlay.playing {\n opacity: 1;\n }\n\n .glide-outlined-phone {\n width: 100px;\n height: 180px;\n border: 4px solid var(--glide-phone-border);\n border-radius: 16px;\n position: relative;\n background: transparent;\n box-shadow: 0 10px 30px rgba(0,0,0,0.2);\n transform: translateY(20px);\n }\n \n /* Notch */\n .glide-outlined-phone::before {\n content: \'\';\n position: absolute;\n top: -1px;\n left: 50%;\n transform: translateX(-50%);\n width: 40%;\n height: 12px;\n background: var(--glide-phone-border);\n border-bottom-left-radius: 8px;\n border-bottom-right-radius: 8px;\n }\n \n /* Scanning Line */\n .glide-scan-line {\n position: absolute;\n top: 10%;\n left: 5%;\n width: 90%;\n height: 2px;\n background: var(--glide-primary);\n box-shadow: 0 0 8px var(--glide-primary);\n opacity: 0;\n }\n \n /* Animation Keyframes */\n @keyframes glide-scan-motion {\n 0% { top: 10%; opacity: 0; }\n 10% { opacity: 1; }\n 90% { opacity: 1; }\n 100% { top: 90%; opacity: 0; }\n }\n \n .glide-phone-animation-overlay.playing .glide-outlined-phone {\n animation: glide-phone-appear 3s ease-in-out forwards;\n }\n \n .glide-phone-animation-overlay.playing .glide-scan-line {\n animation: glide-scan-motion 2s ease-in-out 0.5s infinite;\n }\n \n @keyframes glide-phone-appear {\n 0% { transform: translateY(20px); opacity: 0; }\n 10% { transform: translateY(0); opacity: 1; }\n 90% { transform: translateY(0); opacity: 1; }\n 100% { transform: translateY(20px); opacity: 0; }\n }\n \n /* Dual Mode */\n .glide-dual-container {\n display: flex;\n justify-content: center;\n align-items: stretch;\n gap: 32px;\n margin-top: 20px;\n }\n \n .glide-dual-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n }\n \n .glide-os-logo {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n margin-bottom: 12px;\n font-size: 15px;\n color: inherit;\n }\n \n /* Dual mode OS logo - aligned icons with text, spacing to QR */\n .glide-dual-mode .glide-os-logo {\n margin-bottom: 12px; /* Space between label and QR code */\n }\n \n #glide-modal .glide-dual-mode .glide-os-logo .glide-icon-os,\n #glide-modal .glide-dual-mode .glide-os-logo svg {\n width: var(--glide-dual-icon-size);\n height: var(--glide-dual-icon-size);\n margin: 0;\n padding: 0;\n flex-shrink: 0;\n }\n \n .glide-dual-mode .glide-os-logo span {\n margin: 0;\n padding: 0;\n line-height: 1;\n }\n \n .glide-os-logo svg {\n width: 20px;\n height: 20px;\n opacity: 0.8;\n }\n \n /* Dual Mode Separator - aligned to QR codes only */\n .glide-dual-separator {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n align-self: stretch;\n /* Offset for OS label (18px icon + 12px margin = ~30px) */\n margin-top: 30px;\n padding: 20px 0;\n }\n \n .glide-separator-line {\n width: 1px;\n flex: 1;\n background: linear-gradient(to bottom, transparent, rgba(128,128,128,0.3), transparent);\n }\n \n .glide-separator-text {\n padding: 8px 0;\n font-size: 11px;\n font-weight: 500;\n color: rgba(128,128,128,0.5);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n \n #glide-modal.dark .glide-separator-line {\n background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.2), transparent);\n }\n \n #glide-modal.dark .glide-separator-text {\n color: rgba(255,255,255,0.4);\n }\n \n /* Pre-Step */\n .glide-pre-step-container {\n display: flex;\n gap: 20px;\n justify-content: center;\n margin: 24px 0;\n }\n \n .glide-os-choice-btn {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 140px;\n height: 140px;\n border: 1px solid rgba(0,0,0,0.08);\n border-radius: 20px;\n background: rgba(255,255,255,0.4);\n cursor: pointer;\n transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);\n position: relative;\n overflow: hidden;\n font-size: 14px;\n color: inherit;\n }\n \n #glide-modal.dark .glide-os-choice-btn {\n background: rgba(255,255,255,0.05);\n border-color: rgba(255,255,255,0.1);\n color: white;\n }\n \n .glide-os-choice-btn:hover {\n background: rgba(255,255,255,0.9);\n transform: translateY(-4px);\n box-shadow: 0 12px 24px rgba(0,0,0,0.1), 0 4px 8px rgba(0,0,0,0.04);\n border-color: var(--glide-primary);\n }\n \n #glide-modal.dark .glide-os-choice-btn:hover {\n background: rgba(255,255,255,0.15);\n box-shadow: 0 12px 24px rgba(0,0,0,0.3);\n border-color: var(--glide-primary);\n }\n \n .glide-icon-os {\n width: 40px;\n height: 40px;\n margin-bottom: 12px;\n transition: transform 0.3s;\n fill: currentColor;\n }\n \n .glide-os-choice-btn:hover .glide-icon-os {\n transform: scale(1.1);\n }\n \n #glide-modal .glide-btn-back {\n position: absolute;\n top: 16px;\n left: 16px;\n width: var(--glide-btn-size);\n height: var(--glide-btn-size);\n min-width: var(--glide-btn-size);\n min-height: var(--glide-btn-size);\n max-width: var(--glide-btn-size);\n max-height: var(--glide-btn-size);\n background: rgba(118, 118, 128, 0.12);\n border: none;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n color: rgba(0,0,0,0.5);\n transition: background 0.2s;\n z-index: 20;\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n flex-shrink: 0;\n }\n \n #glide-modal.dark .glide-btn-back {\n background: rgba(255, 255, 255, 0.1);\n color: rgba(255,255,255,0.5);\n }\n\n .glide-btn-back:hover {\n background: rgba(118, 118, 128, 0.2);\n }\n \n #glide-modal.dark .glide-btn-back:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n \n .glide-spinner {\n width: 40px;\n height: 40px;\n border: 3px solid rgba(0,0,0,0.1);\n border-top-color: var(--glide-primary);\n border-radius: 50%;\n animation: glide-spin 1s linear infinite;\n margin: 40px auto;\n }\n \n #glide-modal.dark .glide-spinner {\n border-color: rgba(255,255,255,0.1);\n border-top-color: var(--glide-primary);\n }\n \n @keyframes glide-spin {\n to { transform: rotate(360deg); }\n }\n ',document.head.appendChild(e)}show(){this.container&&this.backdrop&&!this.isOpen?(document.body.appendChild(this.backdrop),document.body.appendChild(this.container),this.lockBodyScroll(),document.addEventListener("keydown",this.handleEscapeKey),requestAnimationFrame(()=>{this.backdrop&&this.container&&(this.backdrop.style.opacity="1",this.container.style.opacity="1",this.container.style.transform="translateX(-50%) scale(1)")}),this.isOpen=!0):this.isOpen&&this.container&&this.backdrop&&(document.removeEventListener("keydown",this.handleEscapeKey),document.addEventListener("keydown",this.handleEscapeKey))}setupPlatformToggles(){const e=this.container?.querySelector("#glide-toggle"),n=this.container?.querySelectorAll(".glide-toggle-btn"),t=this.container?.querySelector("#glide-qr-img"),i=this.container?.querySelector("#glide-platform-message");n&&t&&n.forEach(o=>{o.addEventListener("click",o=>{const r=o.currentTarget,a=r.getAttribute("data-platform");e&&a&&e.setAttribute("data-active",a),n.forEach(e=>e.classList.remove("active")),r.classList.add("active"),"ios"===a?(t.src=t.getAttribute("data-ios")||"",i&&(i.textContent="Scan with your iPhone camera")):"android"===a&&(t.src=t.getAttribute("data-android")||"",i&&(i.textContent="Scan with your Android camera"))})})}lockBodyScroll(){this.originalBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden"}unlockBodyScroll(){document.body.style.overflow=this.originalBodyOverflow}close(){this.container&&this.backdrop&&this.isOpen&&(this.isClosing=!0,document.removeEventListener("keydown",this.handleEscapeKey),this.backdrop.style.opacity="0",this.container.style.opacity="0",this.container.style.transform="translateX(-50%) scale(0.94)",this.closeCallback=void 0,setTimeout(()=>{this.isClosing&&(this.cleanup(),this.isOpen=!1,this.isClosing=!1)},400))}cleanup(){this.container?.remove(),this.backdrop?.remove(),this.container=null,this.backdrop=null,this.unlockBodyScroll()}isModalOpen(){return this.isOpen}}function x(e){const{data:n}=e;if(n.ios_qr_image)return{iosQRCode:n.ios_qr_image,androidQRCode:n.android_qr_image||n.ios_qr_image};if(n.qr_code_image)return n.qr_code_image;throw new Error("No QR code data available")}class w{constructor(){this.logs=[],this.container=null,this.logsContainer=null,this.floatingToggle=null,this.isAtBottom=!0,this.isVisible=!0,this.originalConsole={log:console.log,error:console.error,warn:console.warn,debug:console.debug,info:console.info},this.interceptConsole(),this.createUI()}static init(){return w.instance||(w.instance=new w),w.instance}static destroy(){w.instance&&(w.instance.cleanup(),w.instance=null)}interceptConsole(){["log","error","warn","debug","info"].forEach(e=>{const n=this.originalConsole[e];console[e]=(...t)=>{n.apply(console,t),this.addLog(e,t)}})}addLog(e,n){const t=(new Date).toTimeString().split(" ")[0],i=n.map(e=>{if("object"==typeof e)try{return JSON.stringify(e,null,2)}catch{return"[Object]"}return String(e)}).join(" "),o={log:"#abb2bf",error:"#e06c75",warn:"#e5c07b",info:"#61afef",debug:"#5c6370"},r=`\n <div style="margin: 3px 0; font-family: 'SF Mono', Menlo, Monaco, monospace; font-size: 11px; color: ${o[e]||"#abb2bf"}; line-height: 1.5;">\n <span style="color: #5c6370; font-size: 10px;">${t}</span>\n <span style="background: ${{log:"#3c3c3c",error:"rgba(224, 108, 117, 0.2)",warn:"rgba(229, 192, 123, 0.2)",info:"rgba(97, 175, 239, 0.2)",debug:"#2d2d2d"}[e]}; color: ${o[e]}; padding: 1px 5px; border-radius: 3px; font-size: 9px; font-weight: 500; text-transform: uppercase; margin: 0 6px;">${e}</span>\n <span style="white-space: pre-wrap; word-break: break-all;">${this.escapeHtml(i)}</span>\n </div>\n `;this.logs.push(r),this.logs.length>500&&this.logs.shift(),this.updateDisplay()}updateDisplay(){this.logsContainer&&this.isVisible&&(this.isAtBottom=this.logsContainer.scrollHeight-this.logsContainer.scrollTop<=this.logsContainer.clientHeight+50,this.logsContainer.innerHTML=this.logs.join(""),this.isAtBottom&&(this.logsContainer.scrollTop=this.logsContainer.scrollHeight))}createUI(){const e=document.createElement("style");e.textContent="\n #mobile-debug-console {\n position: fixed;\n bottom: 0;\n left: 0;\n right: 0;\n height: 45vh;\n background: #1e1e1e;\n z-index: 999999;\n display: flex;\n flex-direction: column;\n font-family: 'SF Mono', Menlo, Monaco, 'Courier New', monospace;\n transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n border-top: 1px solid #3c3c3c;\n box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.4);\n }\n \n #mobile-debug-console.hidden {\n transform: translateY(100%);\n }\n \n #debug-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 8px 12px;\n background: #2d2d2d;\n border-bottom: 1px solid #3c3c3c;\n min-height: 36px;\n }\n \n #debug-title {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #9da5b4;\n font-size: 12px;\n font-weight: 500;\n letter-spacing: 0.3px;\n }\n \n #debug-title svg {\n width: 14px;\n height: 14px;\n opacity: 0.8;\n }\n \n /* Traffic light buttons - using ID for specificity */\n #mobile-debug-console .debug-traffic-lights {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n \n #mobile-debug-console button.debug-traffic-btn {\n width: 16px;\n height: 16px;\n min-width: 16px;\n min-height: 16px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0;\n font-size: 0;\n line-height: 1;\n }\n \n #mobile-debug-console .debug-traffic-btn svg {\n width: 8px;\n height: 8px;\n }\n \n #mobile-debug-console .debug-traffic-btn.close {\n background: #ff5f57;\n }\n \n #mobile-debug-console .debug-traffic-btn.close svg {\n stroke: #820005;\n stroke-width: 2;\n }\n \n #mobile-debug-console .debug-traffic-btn.clear {\n background: #febc2e;\n }\n \n #mobile-debug-console .debug-traffic-btn.minimize {\n background: #28c840;\n }\n \n #mobile-debug-console .debug-traffic-btn.minimize svg {\n stroke: #006500;\n stroke-width: 2;\n }\n \n #mobile-debug-console .debug-traffic-btn:active {\n filter: brightness(0.85);\n }\n \n #debug-logs {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n background: #1e1e1e;\n -webkit-overflow-scrolling: touch;\n }\n \n button#debug-floating-toggle {\n position: fixed !important;\n bottom: 20px !important;\n right: 20px !important;\n width: 42px !important;\n height: 42px !important;\n min-width: 42px !important;\n min-height: 42px !important;\n border-radius: 8px !important;\n background: #2d2d2d !important;\n border: 1px solid #3c3c3c !important;\n color: #9da5b4 !important;\n cursor: pointer !important;\n z-index: 999998 !important;\n display: none;\n align-items: center !important;\n justify-content: center !important;\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;\n transition: all 0.2s ease !important;\n padding: 0 !important;\n margin: 0 !important;\n }\n \n button#debug-floating-toggle:hover {\n background: #3c3c3c !important;\n color: #fff !important;\n transform: translateY(-2px) !important;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4) !important;\n }\n \n button#debug-floating-toggle:active {\n transform: translateY(0) !important;\n }\n \n button#debug-floating-toggle.visible {\n display: flex !important;\n }\n \n button#debug-floating-toggle svg {\n width: 20px !important;\n height: 20px !important;\n }\n ",document.head.appendChild(e);const n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>';this.container=document.createElement("div"),this.container.id="mobile-debug-console",this.isVisible||(this.container.className="hidden");const t=document.createElement("div");t.id="debug-header";const i=document.createElement("div");i.id="debug-title",i.innerHTML=`${n}<span>Mobile Console</span>`;const o=document.createElement("div");o.className="debug-traffic-lights";const r=document.createElement("button");r.className="debug-traffic-btn close",r.title="Close",r.innerHTML='<svg viewBox="0 0 10 10" fill="none"><line x1="2.5" y1="2.5" x2="7.5" y2="7.5" stroke="currentColor"/><line x1="7.5" y1="2.5" x2="2.5" y2="7.5" stroke="currentColor"/></svg>',r.onclick=()=>this.cleanup();const a=document.createElement("button");a.className="debug-traffic-btn clear",a.title="Clear",a.innerHTML='<svg viewBox="0 0 16 16" fill="currentColor"><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5m3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0z"/><path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4zM2.5 3h11V2h-11z"/></svg>',a.onclick=()=>this.clear();const s=document.createElement("button");s.className="debug-traffic-btn minimize",s.title="Minimize",s.innerHTML='<svg viewBox="0 0 10 10" fill="none"><path d="M2 3L5 6L8 3" stroke="currentColor" fill="none"/></svg>',s.onclick=()=>this.toggle(),o.appendChild(r),o.appendChild(a),o.appendChild(s),t.appendChild(o),t.appendChild(i),this.logsContainer=document.createElement("div"),this.logsContainer.id="debug-logs",this.logsContainer.addEventListener("scroll",()=>{this.isAtBottom=this.logsContainer.scrollHeight-this.logsContainer.scrollTop<=this.logsContainer.clientHeight+50}),this.container.appendChild(t),this.container.appendChild(this.logsContainer),document.body.appendChild(this.container),this.floatingToggle=document.createElement("button"),this.floatingToggle.id="debug-floating-toggle",this.floatingToggle.innerHTML=n,this.floatingToggle.title="Show Console",this.floatingToggle.onclick=()=>this.toggle(),document.body.appendChild(this.floatingToggle)}escapeHtml(e){const n=document.createElement("div");return n.textContent=e,n.innerHTML}toggle(){this.isVisible=!this.isVisible,this.container&&this.floatingToggle&&(this.isVisible?(this.container.classList.remove("hidden"),this.floatingToggle.classList.remove("visible"),this.updateDisplay()):(this.container.classList.add("hidden"),this.floatingToggle.classList.add("visible")))}clear(){this.logs=[],this.logsContainer&&(this.logsContainer.innerHTML="")}cleanup(){Object.keys(this.originalConsole).forEach(e=>{console[e]=this.originalConsole[e]}),this.container&&this.container.remove(),this.floatingToggle&&this.floatingToggle.remove()}}w.instance=null;class E{constructor(e={}){this.config={...e,endpoints:{prepare:e.endpoints?.prepare||"/api/magic-auth/prepare",process:e.endpoints?.process||"/api/magic-auth/process",polling:e.endpoints?.polling},headers:e.headers,timeout:e.timeout||3e4,pollingInterval:e.pollingInterval||2e3,maxPollingAttempts:e.maxPollingAttempts||30,debug:e.debug||!1,devEnv:e.devEnv},this.http=e.httpClient||function(e={}){const{timeout:n=3e4,headers:t={},dynamicHeaders:i}=e;async function o(e,n){const o={"Content-Type":"application/json"};t.common&&Object.assign(o,t.common);const r=t[e.endpoint];if(r&&"object"==typeof r&&Object.assign(o,r),i){const n=await i(e);Object.assign(o,n)}return n&&Object.assign(o,n),o}async function r(e,n,t,i){const o=new AbortController,r=setTimeout(()=>o.abort(),t),a=i?()=>o.abort():null;i&&a&&i.addEventListener("abort",a);try{return await fetch(e,{...n,signal:o.signal})}catch(e){if(e instanceof Error&&"AbortError"===e.name){if(i?.aborted)throw h(s.CANCELLED,"Request was cancelled");throw h(s.TIMEOUT,"Request timed out")}throw h(s.NETWORK_ERROR,e instanceof Error?e.message:"Network request failed")}finally{clearTimeout(r),i&&a&&i.removeEventListener("abort",a)}}async function a(e){let n;try{n=await e.json()}catch{if(!e.ok)throw h(s.INVALID_RESPONSE,`Request failed with status ${e.status}`);throw h(s.INVALID_RESPONSE,"Failed to parse response")}if(!e.ok)throw function(e){if(e&&"object"==typeof e&&("code"in e||"error"in e)){const n=e,t=n.code||n.error,i=n.message,o=new Error(i||"An error occurred");return o.code=t,o.status=n.status,o.requestId=n.requestId||n.request_id,o.timestamp=n.timestamp,o.details=n.details,o.traceId=n.trace_id||n.traceId,o.spanId=n.span_id||n.spanId,o.service=n.service,n.details&&"object"==typeof n.details&&"retryAfter"in n.details&&(o.retryAfter=n.details.retryAfter),o}if(e&&"object"==typeof e&&"status"in e){const n=e,t=n.status,i=new Error(n.message||`Request failed with status ${t}`);return i.code=`HTTP_${t}`,i.status=t,i}const n=new Error("An unexpected error occurred");return n.code="UNKNOWN_ERROR",n}("object"!=typeof n||null===n||Array.isArray(n)?{status:e.status,rawResponse:n}:{...n,status:e.status});return n}function l(e){return e.includes("/prepare")?"prepare":e.includes("/process")||e.includes("/get-phone")||e.includes("/verify-phone")?"process":e.includes("/status")?"polling":"prepare"}return{async post(e,t,i){const s=l(e),d=await o({endpoint:s,method:"POST"},i?.headers);return a(await r(e,{method:"POST",headers:d,body:JSON.stringify(t)},i?.timeout||n,i?.signal))},async get(e,t){const i=l(e),s=await o({endpoint:i,method:"GET"},t?.headers);return delete s["Content-Type"],a(await r(e,{method:"GET",headers:s},t?.timeout||n,t?.signal))}}}({timeout:this.config.timeout,headers:e.headers,dynamicHeaders:e.dynamicHeaders}),this.logger=e.logger||(this.config.debug?function(e={}){const{debug:n=!1,prefix:t="[PhoneAuth]"}=e;function i(e,n){const i=`${t} ${e}`;return void 0!==n?[i,f(n)]:[i]}return{debug(e,t){if(n){const n=i(e,t);console.log(...n)}},info(e,n){const t=i(e,n);console.info(...t)},warn(e,n){const t=i(e,n);console.warn(...t)},error(e,n){const t=i(e,n);console.error(...t)}}}({debug:!0}):{debug:()=>{},info:()=>{},warn:()=>{},error:()=>{}}),this.logger.debug("PhoneAuthClient initialized",{endpoints:this.config.endpoints,timeout:this.config.timeout,...e.devEnv&&{devEnv:e.devEnv}}),e.devtools?.showMobileConsole&&"undefined"!=typeof window&&(w.init(),this.logger.info("Mobile debug console enabled"))}async authenticate(e,n){const i=await this.prepare(e),o=await this.invokeSecurePrompt(i,n),r=await o.credential,a=i.session.metadata?.use_case||e.use_case;if(!a)throw h(s.MISSING_PARAMETERS,"use_case is required - must be provided in request or returned in session.metadata from parent session");if(a===t.VERIFY_PHONE_NUMBER)return this.verifyPhoneNumber(r,i.session);if(a===t.GET_PHONE_NUMBER)return this.getPhoneNumber(r,i.session);throw h(s.MISSING_PARAMETERS,`Invalid use_case: ${a}`)}async prepare(e){if(this.logger.debug("Preparing authentication",{use_case:e.use_case}),e.phone_number){const n=r(e.phone_number);if(!n.valid)throw h(s.INVALID_PHONE_NUMBER,n.error)}if(e.plmn){const n=a(e.plmn);if(!n.valid)throw h(s.INVALID_PLMN,n.error)}if(!e.use_case&&!e.options?.parent_session_id)throw h(s.MISSING_PARAMETERS,"use_case is required");if(e.use_case){const r=(n=e.use_case,i=e.phone_number,o=!!e.options?.parent_session_id,n!==t.VERIFY_PHONE_NUMBER||i||o?{valid:!0}:{valid:!1,error:"Phone number is required for VerifyPhoneNumber use case"});if(!r.valid)throw h(s.MISSING_PARAMETERS,r.error)}var n,i,o;const l={...e,id:e.id||this.generateRequestId(),client_info:e.client_info||{user_agent:navigator.userAgent,platform:navigator.platform}};try{const e=await this.http.post(this.config.endpoints.prepare,l);return this.logger.debug("Prepare successful",{strategy:e.authentication_strategy,sessionKey:e.session.session_key,useCase:e.session.metadata?.use_case}),e}catch(e){throw this.logger.error("Prepare failed",e),e}}async invokeSecurePrompt(e,n){const{authentication_strategy:t,session:o,data:r}=e;switch(this.logger.debug("Invoking secure prompt",{strategy:t}),t){case i.TS43:return this.handleTS43(r,o);case i.LINK:return this.handleLink(r,o,n);case i.DESKTOP:return this.handleDesktop(r,o,n);default:throw h(s.UNSUPPORTED_STRATEGY,`Unknown strategy: ${t}`)}}async getPhoneNumber(e,n){this.logger.debug("Getting phone number");const i={session:n,credential:e,use_case:t.GET_PHONE_NUMBER};try{const e=await this.http.post(this.config.endpoints.process,i);return this.logger.info("Phone number retrieved",{hasPhoneNumber:!!e.phone_number,phoneNumberLength:e.phone_number?.length}),e}catch(e){throw this.logger.error("Get phone number failed",e),e}}async verifyPhoneNumber(e,n){this.logger.debug("Verifying phone number");const i={session:n,credential:e,use_case:t.VERIFY_PHONE_NUMBER};try{const e=await this.http.post(this.config.endpoints.process,i);return this.logger.info("Phone number verified",{verified:e.verified}),e}catch(e){throw this.logger.error("Verify phone number failed",e),e}}isSupported(){return"undefined"!=typeof window&&"DigitalCredential"in window}getBrowserSupportInfo(){if("undefined"==typeof window)return{supported:!1,browser:"unknown",message:"Not in browser"};const e=navigator.userAgent,n=/Chrome/.test(e)&&/Google Inc/.test(navigator.vendor),t=/Edg\//.test(e);return this.isSupported()?{supported:!0,browser:n?"Chrome":t?"Edge":"Other"}:{supported:!1,browser:n?"Chrome":t?"Edge":"Other",message:"Enable chrome://flags/#web-identity-digital-credentials"}}async handleTS43(e,n){if(!this.isSupported())throw h(s.BROWSER_NOT_SUPPORTED,"Digital Credentials API not available");const t={digital:{requests:[{protocol:e.protocol,data:e.data}]}};return this.logger.debug("Invoking Digital Credentials API"),{credential:(async()=>{try{const e=await navigator.credentials.get(t);if(!e?.data?.vp_token)throw h(s.INVALID_RESPONSE,"No credential returned from Digital Credentials API");const n=e.data.vp_token,i="string"==typeof n?n:Object.values(n)[0],o=Array.isArray(i)?i[0]:i;if(!o||"string"==typeof o&&""===o.trim())throw h(s.INVALID_RESPONSE,"Empty credential returned from Digital Credentials API");return this.logger.debug("Digital Credentials API success",{credentialLength:"string"==typeof o?o.length:"unknown",hasCredential:!!o}),"undefined"!=typeof navigator&&navigator.vibrate&&setTimeout(()=>{try{navigator.vibrate([80,50,80])}catch(e){}},200),o}catch(e){if(d(e))throw e;const n=e;if("NotAllowedError"===n.name)throw h(s.USER_CANCELLED,"User cancelled authentication",void 0,n);if(!("NetworkError"!==n.name||19!==n.code||n.message&&(n.message.toLowerCase().includes("token")||n.message.toLowerCase().includes("network")||n.message.toLowerCase().includes("failed")||n.message.toLowerCase().includes("fetch")||n.message.toLowerCase().includes("timeout"))))throw h(s.USER_CANCELLED,"User cancelled authentication",void 0,n);if("NotSupportedError"===n.name)throw h(s.BROWSER_NOT_SUPPORTED,"Browser not supported",void 0,n);throw h(s.NETWORK_ERROR,n.message||"Credential request failed",void 0,n)}})(),cancel:void 0,strategy:i.TS43,session:n}}handleLink(e,n,t){if(!e.url)throw h(s.INVALID_RESPONSE,"Missing link URL");this.logger.debug("Opening App Clip",{url:e.url}),window.location.href=e.url;const o={...this.config.headers?.common,...this.config.headers?.polling};this.config.devEnv&&(o.developer=this.config.devEnv,this.logger.debug("Adding developer header for polling",{devEnv:this.config.devEnv}));const r=v({sessionKey:n.session_key,interval:t?.pollingInterval||this.config.pollingInterval,maxAttempts:t?.maxPollingAttempts||this.config.maxPollingAttempts,pollingEndpoint:t?.pollingEndpoint||this.config.endpoints.polling,statusUrl:e.status_url,logger:this.logger,headers:Object.keys(o).length>0?o:void 0});return{credential:r.start().then(e=>{if("completed"===e.status&&e.credential)return this.logger.debug("Link authentication completed",{hasCredential:!!e.credential,credentialLength:e.credential?.length}),e.credential;throw h(s.VERIFICATION_FAILED,e.message||"Link authentication failed")}),cancel:()=>r.cancel(),strategy:i.LINK,session:n}}handleDesktop(e,n,t){const o=e.data?.session_id||n.session_key;this.logger.debug("Starting desktop authentication",{sessionId:o});const r={...this.config.headers?.common,...this.config.headers?.polling};this.config.devEnv&&(r.developer=this.config.devEnv,this.logger.debug("Adding developer header for polling",{devEnv:this.config.devEnv}));const a=v({sessionKey:o,interval:t?.pollingInterval||this.config.pollingInterval,maxAttempts:t?.maxPollingAttempts||this.config.maxPollingAttempts,pollingEndpoint:t?.pollingEndpoint||this.config.endpoints.polling,statusUrl:e.data?.status_url,logger:this.logger,headers:Object.keys(r).length>0?r:void 0});let l=null;if(!t?.preventDefaultUI)try{const n=x(e);l=new y(t?.modalOptions),l.showQRCode(n,t?.modalOptions?.description||"Scan with your phone camera"),l.setCloseCallback(()=>{this.logger.debug("Modal closed by user, cancelling authentication"),a.cancel()}),this.logger.debug("Desktop modal displayed")}catch(e){this.logger.warn("Failed to show modal, continuing with polling only",e)}return{credential:a.start().then(e=>{if(l&&l.close(),"completed"===e.status&&e.credential)return this.logger.debug("Desktop authentication completed",{hasCredential:!!e.credential,credentialLength:e.credential?.length}),e.credential;throw h(s.VERIFICATION_FAILED,e.message||"Desktop authentication failed")}).catch(e=>{throw l&&l.close(),e}),cancel:()=>{a.cancel(),l&&l.close()},strategy:i.DESKTOP,session:n}}generateRequestId(){return`web-${Date.now()}-${Math.random().toString(36).substring(2,11)}`}}function k(e){return null!==e&&"object"==typeof e&&"credential"in e&&"strategy"in e&&"session"in e}function C(e){return null!==e&&"object"==typeof e&&"credential"in e&&"authenticated"in e&&"session"in e}function S(e){return e.strategy===i.TS43}function A(e){return e.strategy===i.LINK}function R(e){return e.strategy===i.DESKTOP}function _(e){return void 0!==e.cancel}function I(e){return null!==e&&"object"==typeof e&&"protocol"in e&&"data"in e&&"object"==typeof e.data&&"dcql_query"in e.data}function N(e){return null!==e&&"object"==typeof e&&"url"in e&&"string"==typeof e.url}function T(e){return null!==e&&"object"==typeof e&&"data"in e&&"object"==typeof e.data&&null!==e.data&&!("dcql_query"in e.data)}function O(e){return!("verified"in e)}function P(e){return"verified"in e}function L(e){return null!==e&&"object"==typeof e&&"code"in e&&"message"in e}return n})());
@@ -36,6 +36,22 @@ exports.createAuthError = exports.isAuthError = exports.ERROR_CODES = exports.AU
36
36
  exports.usePhoneAuth = usePhoneAuth;
37
37
  const vue_1 = require("vue");
38
38
  const phone_auth_client_1 = require("../client/phone-auth-client");
39
+ // ============================================================================
40
+ // HELPER FUNCTIONS
41
+ // ============================================================================
42
+ /**
43
+ * Unwrap Vue reactive proxy to get raw object.
44
+ * This ensures objects work correctly with browser APIs (like Digital Credentials)
45
+ * that may not handle Vue proxies properly.
46
+ *
47
+ * Safe to call on non-proxy objects - returns them unchanged.
48
+ */
49
+ function unwrapProxy(obj) {
50
+ if (obj === null || obj === undefined)
51
+ return obj;
52
+ // toRaw returns the original object if it's not a proxy
53
+ return (0, vue_1.toRaw)(obj);
54
+ }
39
55
  // Re-export PhoneAuthClient and core types/constants for convenience
40
56
  var phone_auth_client_2 = require("../client/phone-auth-client");
41
57
  Object.defineProperty(exports, "PhoneAuthClient", { enumerable: true, get: function () { return phone_auth_client_2.PhoneAuthClient; } });
@@ -67,7 +83,10 @@ function usePhoneAuth(config) {
67
83
  */
68
84
  async function authenticate(request, options) {
69
85
  try {
70
- const authResult = await client.authenticate(request, options);
86
+ // Unwrap Vue proxies to ensure browser APIs work correctly
87
+ const rawRequest = unwrapProxy(request);
88
+ const rawOptions = options ? unwrapProxy(options) : undefined;
89
+ const authResult = await client.authenticate(rawRequest, rawOptions);
71
90
  result.value = authResult;
72
91
  error.value = null;
73
92
  step.value = 'complete';
@@ -89,9 +108,11 @@ function usePhoneAuth(config) {
89
108
  error.value = null;
90
109
  step.value = 'preparing';
91
110
  try {
92
- const result = await client.prepare(request);
111
+ // Unwrap Vue proxy to ensure clean data is sent to backend
112
+ const rawRequest = unwrapProxy(request);
113
+ const prepareResult = await client.prepare(rawRequest);
93
114
  step.value = 'idle'; // Reset step on success (prepare is just first step)
94
- return result;
115
+ return prepareResult;
95
116
  }
96
117
  catch (err) {
97
118
  error.value = err;
@@ -105,10 +126,16 @@ function usePhoneAuth(config) {
105
126
  /**
106
127
  * Granular: Invoke secure prompt.
107
128
  * Must be called from a user gesture (button click).
129
+ *
130
+ * Note: Automatically unwraps Vue reactive proxies to ensure compatibility
131
+ * with browser APIs like Digital Credentials.
108
132
  */
109
133
  async function invokeSecurePrompt(prepared, options) {
110
134
  try {
111
- const invokeResult = await client.invokeSecurePrompt(prepared, options);
135
+ // Unwrap Vue proxies - critical for Digital Credentials API compatibility
136
+ const rawPrepared = unwrapProxy(prepared);
137
+ const rawOptions = options ? unwrapProxy(options) : undefined;
138
+ const invokeResult = await client.invokeSecurePrompt(rawPrepared, rawOptions);
112
139
  isLoading.value = false;
113
140
  error.value = null;
114
141
  step.value = 'idle';
@@ -129,7 +156,9 @@ function usePhoneAuth(config) {
129
156
  error.value = null;
130
157
  step.value = 'processing';
131
158
  try {
132
- const authResult = await client.getPhoneNumber(credential, session);
159
+ // Unwrap Vue proxy from session object
160
+ const rawSession = unwrapProxy(session);
161
+ const authResult = await client.getPhoneNumber(credential, rawSession);
133
162
  result.value = authResult;
134
163
  step.value = 'complete';
135
164
  return authResult;
@@ -151,7 +180,9 @@ function usePhoneAuth(config) {
151
180
  error.value = null;
152
181
  step.value = 'processing';
153
182
  try {
154
- const authResult = await client.verifyPhoneNumber(credential, session);
183
+ // Unwrap Vue proxy from session object
184
+ const rawSession = unwrapProxy(session);
185
+ const authResult = await client.verifyPhoneNumber(credential, rawSession);
155
186
  result.value = authResult;
156
187
  step.value = 'complete';
157
188
  return authResult;
@@ -98,7 +98,9 @@ function createLogger(config = {}) {
98
98
  debug(message, data) {
99
99
  if (debug) {
100
100
  const args = format(message, data);
101
- console.debug(...args);
101
+ // Use console.log instead of console.debug for visibility
102
+ // (console.debug is filtered by default in most browsers)
103
+ console.log(...args);
102
104
  }
103
105
  },
104
106
  info(message, data) {
@@ -84,21 +84,26 @@ class PhoneAuthClient {
84
84
  // Step 3: Wait for credential and process
85
85
  const credential = await invokeResult.credential;
86
86
  // Determine use_case from (in priority order):
87
- // 1. session.use_case (direct field)
88
- // 2. session.metadata.use_case (server returns it in metadata)
89
- // 3. request.use_case (fallback to original request)
90
- const useCase = prepared.session.use_case
91
- || prepared.session.metadata?.use_case
92
- || request.use_case;
87
+ // 1. session.metadata.use_case (server returns it in metadata)
88
+ // 2. request.use_case (fallback to original request)
89
+ const useCase = (prepared.session.metadata?.use_case || request.use_case);
90
+ // Double-check: use_case must be resolved at this point.
91
+ // prepare() validates that either use_case OR parent_session_id is provided.
92
+ // When parent_session_id is used, the backend should return use_case in session.metadata.
93
+ // This validation catches edge cases where the backend doesn't return it (e.g., old backend).
93
94
  if (!useCase) {
94
- throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.INVALID_RESPONSE, 'Could not determine use_case from session or request');
95
+ throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.MISSING_PARAMETERS, 'use_case is required - must be provided in request or returned in session.metadata from parent session');
95
96
  }
96
97
  if (useCase === core_1.USE_CASE.VERIFY_PHONE_NUMBER) {
97
98
  return this.verifyPhoneNumber(credential, prepared.session);
98
99
  }
99
- else {
100
+ else if (useCase === core_1.USE_CASE.GET_PHONE_NUMBER) {
100
101
  return this.getPhoneNumber(credential, prepared.session);
101
102
  }
103
+ else {
104
+ // Should never reach here due to validation above, but TypeScript needs this
105
+ throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.MISSING_PARAMETERS, `Invalid use_case: ${useCase}`);
106
+ }
102
107
  }
103
108
  // ==========================================================================
104
109
  // PUBLIC API - Granular Steps
@@ -149,6 +154,7 @@ class PhoneAuthClient {
149
154
  this.logger.debug('Prepare successful', {
150
155
  strategy: response.authentication_strategy,
151
156
  sessionKey: response.session.session_key,
157
+ useCase: response.session.metadata?.use_case,
152
158
  });
153
159
  return response;
154
160
  }
@@ -194,7 +200,10 @@ class PhoneAuthClient {
194
200
  };
195
201
  try {
196
202
  const response = await this.http.post(this.config.endpoints.process, requestBody);
197
- this.logger.info('Phone number retrieved');
203
+ this.logger.info('Phone number retrieved', {
204
+ hasPhoneNumber: !!response.phone_number,
205
+ phoneNumberLength: response.phone_number?.length,
206
+ });
198
207
  return response;
199
208
  }
200
209
  catch (error) {
@@ -297,6 +306,11 @@ class PhoneAuthClient {
297
306
  if (!credential || (typeof credential === 'string' && credential.trim() === '')) {
298
307
  throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.INVALID_RESPONSE, 'Empty credential returned from Digital Credentials API');
299
308
  }
309
+ // Log success with credential length (not the actual credential for security)
310
+ this.logger.debug('Digital Credentials API success', {
311
+ credentialLength: typeof credential === 'string' ? credential.length : 'unknown',
312
+ hasCredential: !!credential,
313
+ });
300
314
  // Success haptic feedback
301
315
  if (typeof navigator !== 'undefined' && navigator.vibrate) {
302
316
  // Add a small delay to ensure the browser has regained focus/visibility
@@ -319,16 +333,32 @@ class PhoneAuthClient {
319
333
  if ((0, errors_1.isAuthError)(error)) {
320
334
  throw error;
321
335
  }
322
- // Map browser errors to SDK errors
336
+ // Map browser errors to SDK errors, preserving original error
323
337
  const err = error;
324
- if (err.name === 'NotAllowedError' ||
325
- (err.name === 'NetworkError' && err.code === 19)) {
326
- throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.USER_CANCELLED, 'User cancelled authentication');
338
+ // NotAllowedError is specifically for user cancellation/denial
339
+ if (err.name === 'NotAllowedError') {
340
+ throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.USER_CANCELLED, 'User cancelled authentication', undefined, err);
341
+ }
342
+ // NetworkError code 19 = AbortError (user cancelled via abort signal)
343
+ // But only if message doesn't indicate a real network failure
344
+ if (err.name === 'NetworkError' && err.code === 19) {
345
+ // Check for specific terms that indicate a real network/token failure
346
+ // Note: Don't check for generic 'error' as it's too broad and would
347
+ // misclassify user cancellations like "Abort error" or "Operation cancelled"
348
+ const isRealNetworkError = err.message && (err.message.toLowerCase().includes('token') ||
349
+ err.message.toLowerCase().includes('network') ||
350
+ err.message.toLowerCase().includes('failed') ||
351
+ err.message.toLowerCase().includes('fetch') ||
352
+ err.message.toLowerCase().includes('timeout'));
353
+ if (!isRealNetworkError) {
354
+ throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.USER_CANCELLED, 'User cancelled authentication', undefined, err);
355
+ }
327
356
  }
328
357
  if (err.name === 'NotSupportedError') {
329
- throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.BROWSER_NOT_SUPPORTED, 'Browser not supported');
358
+ throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.BROWSER_NOT_SUPPORTED, 'Browser not supported', undefined, err);
330
359
  }
331
- throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.NETWORK_ERROR, err.message || 'Credential request failed');
360
+ // All other errors (including NetworkError with descriptive messages) are network errors
361
+ throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.NETWORK_ERROR, err.message || 'Credential request failed', undefined, err);
332
362
  }
333
363
  })();
334
364
  // TS43 returns immediately (no cancel needed)
@@ -374,6 +404,10 @@ class PhoneAuthClient {
374
404
  // Create credential promise from polling - resolves to just the credential string
375
405
  const credentialPromise = polling.start().then(result => {
376
406
  if (result.status === 'completed' && result.credential) {
407
+ this.logger.debug('Link authentication completed', {
408
+ hasCredential: !!result.credential,
409
+ credentialLength: result.credential?.length,
410
+ });
377
411
  return result.credential;
378
412
  }
379
413
  throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.VERIFICATION_FAILED, result.message || 'Link authentication failed');
@@ -439,6 +473,10 @@ class PhoneAuthClient {
439
473
  modal.close();
440
474
  }
441
475
  if (result.status === 'completed' && result.credential) {
476
+ this.logger.debug('Desktop authentication completed', {
477
+ hasCredential: !!result.credential,
478
+ credentialLength: result.credential?.length,
479
+ });
442
480
  return result.credential;
443
481
  }
444
482
  throw (0, errors_1.createAuthError)(errors_1.ERROR_CODES.VERIFICATION_FAILED, result.message || 'Desktop authentication failed');
@@ -104,13 +104,25 @@ function getUserMessage(error) {
104
104
  * @example
105
105
  * ```typescript
106
106
  * throw createAuthError('INVALID_PHONE_NUMBER', 'Phone number must start with +');
107
+ * // With original error preserved:
108
+ * throw createAuthError('USER_CANCELLED', 'User cancelled', undefined, originalError);
107
109
  * ```
108
110
  */
109
- function createAuthError(code, message, details) {
111
+ function createAuthError(code, message, details, cause) {
110
112
  const error = new Error(message || CLIENT_ERROR_MESSAGES[code] || code);
111
113
  error.code = code;
112
114
  error.details = details;
113
115
  error.timestamp = new Date().toISOString();
116
+ // Preserve original error for debugging
117
+ if (cause) {
118
+ error.cause = cause;
119
+ const causeWithCode = cause;
120
+ error.browserError = {
121
+ name: cause.name,
122
+ message: cause.message,
123
+ code: causeWithCode.code,
124
+ };
125
+ }
114
126
  return error;
115
127
  }
116
128
  /**
@@ -14,9 +14,11 @@ const types_1 = require("../core/types");
14
14
  // ============================================================================
15
15
  exports.validSession = {
16
16
  session_key: 'test-session-key-12345678',
17
- use_case: types_1.USE_CASE.GET_PHONE_NUMBER,
18
17
  nonce: 'abc123nonce',
19
- metadata: { request_id: 'req-123' },
18
+ metadata: {
19
+ request_id: 'req-123',
20
+ use_case: types_1.USE_CASE.GET_PHONE_NUMBER,
21
+ },
20
22
  };
21
23
  exports.minimalSession = {
22
24
  session_key: 'minimal-session-1234567',
@@ -89,6 +89,7 @@ async function advanceTimersAndFlush(ms) {
89
89
  */
90
90
  function createConsoleMocks() {
91
91
  return {
92
+ log: jest.spyOn(console, 'log').mockImplementation(),
92
93
  debug: jest.spyOn(console, 'debug').mockImplementation(),
93
94
  info: jest.spyOn(console, 'info').mockImplementation(),
94
95
  warn: jest.spyOn(console, 'warn').mockImplementation(),
@@ -99,6 +100,7 @@ function createConsoleMocks() {
99
100
  * Restore console mocks.
100
101
  */
101
102
  function restoreConsoleMocks(mocks) {
103
+ mocks.log.mockRestore();
102
104
  mocks.debug.mockRestore();
103
105
  mocks.info.mockRestore();
104
106
  mocks.warn.mockRestore();
@@ -30,8 +30,24 @@
30
30
  * </template>
31
31
  * ```
32
32
  */
33
- import { ref, computed } from 'vue';
33
+ import { ref, computed, toRaw } from 'vue';
34
34
  import { PhoneAuthClient } from '../client/phone-auth-client';
35
+ // ============================================================================
36
+ // HELPER FUNCTIONS
37
+ // ============================================================================
38
+ /**
39
+ * Unwrap Vue reactive proxy to get raw object.
40
+ * This ensures objects work correctly with browser APIs (like Digital Credentials)
41
+ * that may not handle Vue proxies properly.
42
+ *
43
+ * Safe to call on non-proxy objects - returns them unchanged.
44
+ */
45
+ function unwrapProxy(obj) {
46
+ if (obj === null || obj === undefined)
47
+ return obj;
48
+ // toRaw returns the original object if it's not a proxy
49
+ return toRaw(obj);
50
+ }
35
51
  // Re-export PhoneAuthClient and core types/constants for convenience
36
52
  export { PhoneAuthClient } from '../client/phone-auth-client';
37
53
  export { USE_CASE, AUTHENTICATION_STRATEGY } from '../core/types';
@@ -57,7 +73,10 @@ export function usePhoneAuth(config) {
57
73
  */
58
74
  async function authenticate(request, options) {
59
75
  try {
60
- const authResult = await client.authenticate(request, options);
76
+ // Unwrap Vue proxies to ensure browser APIs work correctly
77
+ const rawRequest = unwrapProxy(request);
78
+ const rawOptions = options ? unwrapProxy(options) : undefined;
79
+ const authResult = await client.authenticate(rawRequest, rawOptions);
61
80
  result.value = authResult;
62
81
  error.value = null;
63
82
  step.value = 'complete';
@@ -79,9 +98,11 @@ export function usePhoneAuth(config) {
79
98
  error.value = null;
80
99
  step.value = 'preparing';
81
100
  try {
82
- const result = await client.prepare(request);
101
+ // Unwrap Vue proxy to ensure clean data is sent to backend
102
+ const rawRequest = unwrapProxy(request);
103
+ const prepareResult = await client.prepare(rawRequest);
83
104
  step.value = 'idle'; // Reset step on success (prepare is just first step)
84
- return result;
105
+ return prepareResult;
85
106
  }
86
107
  catch (err) {
87
108
  error.value = err;
@@ -95,10 +116,16 @@ export function usePhoneAuth(config) {
95
116
  /**
96
117
  * Granular: Invoke secure prompt.
97
118
  * Must be called from a user gesture (button click).
119
+ *
120
+ * Note: Automatically unwraps Vue reactive proxies to ensure compatibility
121
+ * with browser APIs like Digital Credentials.
98
122
  */
99
123
  async function invokeSecurePrompt(prepared, options) {
100
124
  try {
101
- const invokeResult = await client.invokeSecurePrompt(prepared, options);
125
+ // Unwrap Vue proxies - critical for Digital Credentials API compatibility
126
+ const rawPrepared = unwrapProxy(prepared);
127
+ const rawOptions = options ? unwrapProxy(options) : undefined;
128
+ const invokeResult = await client.invokeSecurePrompt(rawPrepared, rawOptions);
102
129
  isLoading.value = false;
103
130
  error.value = null;
104
131
  step.value = 'idle';
@@ -119,7 +146,9 @@ export function usePhoneAuth(config) {
119
146
  error.value = null;
120
147
  step.value = 'processing';
121
148
  try {
122
- const authResult = await client.getPhoneNumber(credential, session);
149
+ // Unwrap Vue proxy from session object
150
+ const rawSession = unwrapProxy(session);
151
+ const authResult = await client.getPhoneNumber(credential, rawSession);
123
152
  result.value = authResult;
124
153
  step.value = 'complete';
125
154
  return authResult;
@@ -141,7 +170,9 @@ export function usePhoneAuth(config) {
141
170
  error.value = null;
142
171
  step.value = 'processing';
143
172
  try {
144
- const authResult = await client.verifyPhoneNumber(credential, session);
173
+ // Unwrap Vue proxy from session object
174
+ const rawSession = unwrapProxy(session);
175
+ const authResult = await client.verifyPhoneNumber(credential, rawSession);
145
176
  result.value = authResult;
146
177
  step.value = 'complete';
147
178
  return authResult;
@@ -94,7 +94,9 @@ export function createLogger(config = {}) {
94
94
  debug(message, data) {
95
95
  if (debug) {
96
96
  const args = format(message, data);
97
- console.debug(...args);
97
+ // Use console.log instead of console.debug for visibility
98
+ // (console.debug is filtered by default in most browsers)
99
+ console.log(...args);
98
100
  }
99
101
  },
100
102
  info(message, data) {
@@ -81,21 +81,26 @@ export class PhoneAuthClient {
81
81
  // Step 3: Wait for credential and process
82
82
  const credential = await invokeResult.credential;
83
83
  // Determine use_case from (in priority order):
84
- // 1. session.use_case (direct field)
85
- // 2. session.metadata.use_case (server returns it in metadata)
86
- // 3. request.use_case (fallback to original request)
87
- const useCase = prepared.session.use_case
88
- || prepared.session.metadata?.use_case
89
- || request.use_case;
84
+ // 1. session.metadata.use_case (server returns it in metadata)
85
+ // 2. request.use_case (fallback to original request)
86
+ const useCase = (prepared.session.metadata?.use_case || request.use_case);
87
+ // Double-check: use_case must be resolved at this point.
88
+ // prepare() validates that either use_case OR parent_session_id is provided.
89
+ // When parent_session_id is used, the backend should return use_case in session.metadata.
90
+ // This validation catches edge cases where the backend doesn't return it (e.g., old backend).
90
91
  if (!useCase) {
91
- throw createAuthError(ERROR_CODES.INVALID_RESPONSE, 'Could not determine use_case from session or request');
92
+ throw createAuthError(ERROR_CODES.MISSING_PARAMETERS, 'use_case is required - must be provided in request or returned in session.metadata from parent session');
92
93
  }
93
94
  if (useCase === USE_CASE.VERIFY_PHONE_NUMBER) {
94
95
  return this.verifyPhoneNumber(credential, prepared.session);
95
96
  }
96
- else {
97
+ else if (useCase === USE_CASE.GET_PHONE_NUMBER) {
97
98
  return this.getPhoneNumber(credential, prepared.session);
98
99
  }
100
+ else {
101
+ // Should never reach here due to validation above, but TypeScript needs this
102
+ throw createAuthError(ERROR_CODES.MISSING_PARAMETERS, `Invalid use_case: ${useCase}`);
103
+ }
99
104
  }
100
105
  // ==========================================================================
101
106
  // PUBLIC API - Granular Steps
@@ -146,6 +151,7 @@ export class PhoneAuthClient {
146
151
  this.logger.debug('Prepare successful', {
147
152
  strategy: response.authentication_strategy,
148
153
  sessionKey: response.session.session_key,
154
+ useCase: response.session.metadata?.use_case,
149
155
  });
150
156
  return response;
151
157
  }
@@ -191,7 +197,10 @@ export class PhoneAuthClient {
191
197
  };
192
198
  try {
193
199
  const response = await this.http.post(this.config.endpoints.process, requestBody);
194
- this.logger.info('Phone number retrieved');
200
+ this.logger.info('Phone number retrieved', {
201
+ hasPhoneNumber: !!response.phone_number,
202
+ phoneNumberLength: response.phone_number?.length,
203
+ });
195
204
  return response;
196
205
  }
197
206
  catch (error) {
@@ -294,6 +303,11 @@ export class PhoneAuthClient {
294
303
  if (!credential || (typeof credential === 'string' && credential.trim() === '')) {
295
304
  throw createAuthError(ERROR_CODES.INVALID_RESPONSE, 'Empty credential returned from Digital Credentials API');
296
305
  }
306
+ // Log success with credential length (not the actual credential for security)
307
+ this.logger.debug('Digital Credentials API success', {
308
+ credentialLength: typeof credential === 'string' ? credential.length : 'unknown',
309
+ hasCredential: !!credential,
310
+ });
297
311
  // Success haptic feedback
298
312
  if (typeof navigator !== 'undefined' && navigator.vibrate) {
299
313
  // Add a small delay to ensure the browser has regained focus/visibility
@@ -316,16 +330,32 @@ export class PhoneAuthClient {
316
330
  if (isAuthError(error)) {
317
331
  throw error;
318
332
  }
319
- // Map browser errors to SDK errors
333
+ // Map browser errors to SDK errors, preserving original error
320
334
  const err = error;
321
- if (err.name === 'NotAllowedError' ||
322
- (err.name === 'NetworkError' && err.code === 19)) {
323
- throw createAuthError(ERROR_CODES.USER_CANCELLED, 'User cancelled authentication');
335
+ // NotAllowedError is specifically for user cancellation/denial
336
+ if (err.name === 'NotAllowedError') {
337
+ throw createAuthError(ERROR_CODES.USER_CANCELLED, 'User cancelled authentication', undefined, err);
338
+ }
339
+ // NetworkError code 19 = AbortError (user cancelled via abort signal)
340
+ // But only if message doesn't indicate a real network failure
341
+ if (err.name === 'NetworkError' && err.code === 19) {
342
+ // Check for specific terms that indicate a real network/token failure
343
+ // Note: Don't check for generic 'error' as it's too broad and would
344
+ // misclassify user cancellations like "Abort error" or "Operation cancelled"
345
+ const isRealNetworkError = err.message && (err.message.toLowerCase().includes('token') ||
346
+ err.message.toLowerCase().includes('network') ||
347
+ err.message.toLowerCase().includes('failed') ||
348
+ err.message.toLowerCase().includes('fetch') ||
349
+ err.message.toLowerCase().includes('timeout'));
350
+ if (!isRealNetworkError) {
351
+ throw createAuthError(ERROR_CODES.USER_CANCELLED, 'User cancelled authentication', undefined, err);
352
+ }
324
353
  }
325
354
  if (err.name === 'NotSupportedError') {
326
- throw createAuthError(ERROR_CODES.BROWSER_NOT_SUPPORTED, 'Browser not supported');
355
+ throw createAuthError(ERROR_CODES.BROWSER_NOT_SUPPORTED, 'Browser not supported', undefined, err);
327
356
  }
328
- throw createAuthError(ERROR_CODES.NETWORK_ERROR, err.message || 'Credential request failed');
357
+ // All other errors (including NetworkError with descriptive messages) are network errors
358
+ throw createAuthError(ERROR_CODES.NETWORK_ERROR, err.message || 'Credential request failed', undefined, err);
329
359
  }
330
360
  })();
331
361
  // TS43 returns immediately (no cancel needed)
@@ -371,6 +401,10 @@ export class PhoneAuthClient {
371
401
  // Create credential promise from polling - resolves to just the credential string
372
402
  const credentialPromise = polling.start().then(result => {
373
403
  if (result.status === 'completed' && result.credential) {
404
+ this.logger.debug('Link authentication completed', {
405
+ hasCredential: !!result.credential,
406
+ credentialLength: result.credential?.length,
407
+ });
374
408
  return result.credential;
375
409
  }
376
410
  throw createAuthError(ERROR_CODES.VERIFICATION_FAILED, result.message || 'Link authentication failed');
@@ -436,6 +470,10 @@ export class PhoneAuthClient {
436
470
  modal.close();
437
471
  }
438
472
  if (result.status === 'completed' && result.credential) {
473
+ this.logger.debug('Desktop authentication completed', {
474
+ hasCredential: !!result.credential,
475
+ credentialLength: result.credential?.length,
476
+ });
439
477
  return result.credential;
440
478
  }
441
479
  throw createAuthError(ERROR_CODES.VERIFICATION_FAILED, result.message || 'Desktop authentication failed');
@@ -93,13 +93,25 @@ export function getUserMessage(error) {
93
93
  * @example
94
94
  * ```typescript
95
95
  * throw createAuthError('INVALID_PHONE_NUMBER', 'Phone number must start with +');
96
+ * // With original error preserved:
97
+ * throw createAuthError('USER_CANCELLED', 'User cancelled', undefined, originalError);
96
98
  * ```
97
99
  */
98
- export function createAuthError(code, message, details) {
100
+ export function createAuthError(code, message, details, cause) {
99
101
  const error = new Error(message || CLIENT_ERROR_MESSAGES[code] || code);
100
102
  error.code = code;
101
103
  error.details = details;
102
104
  error.timestamp = new Date().toISOString();
105
+ // Preserve original error for debugging
106
+ if (cause) {
107
+ error.cause = cause;
108
+ const causeWithCode = cause;
109
+ error.browserError = {
110
+ name: cause.name,
111
+ message: cause.message,
112
+ code: causeWithCode.code,
113
+ };
114
+ }
103
115
  return error;
104
116
  }
105
117
  /**
@@ -11,9 +11,11 @@ import { AUTHENTICATION_STRATEGY, USE_CASE } from '../core/types';
11
11
  // ============================================================================
12
12
  export const validSession = {
13
13
  session_key: 'test-session-key-12345678',
14
- use_case: USE_CASE.GET_PHONE_NUMBER,
15
14
  nonce: 'abc123nonce',
16
- metadata: { request_id: 'req-123' },
15
+ metadata: {
16
+ request_id: 'req-123',
17
+ use_case: USE_CASE.GET_PHONE_NUMBER,
18
+ },
17
19
  };
18
20
  export const minimalSession = {
19
21
  session_key: 'minimal-session-1234567',
@@ -82,6 +82,7 @@ export async function advanceTimersAndFlush(ms) {
82
82
  */
83
83
  export function createConsoleMocks() {
84
84
  return {
85
+ log: jest.spyOn(console, 'log').mockImplementation(),
85
86
  debug: jest.spyOn(console, 'debug').mockImplementation(),
86
87
  info: jest.spyOn(console, 'info').mockImplementation(),
87
88
  warn: jest.spyOn(console, 'warn').mockImplementation(),
@@ -92,6 +93,7 @@ export function createConsoleMocks() {
92
93
  * Restore console mocks.
93
94
  */
94
95
  export function restoreConsoleMocks(mocks) {
96
+ mocks.log.mockRestore();
95
97
  mocks.debug.mockRestore();
96
98
  mocks.info.mockRestore();
97
99
  mocks.warn.mockRestore();
@@ -1 +1 @@
1
- {"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EAET,WAAW,EACZ,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,SAAS,EACT,cAAc,EACd,WAAW,EACX,OAAO,EACP,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAMvB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAM/F;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;4BAiBnC,cAAc,YACb,aAAa,KACtB,OAAO,CAAC,eAAe,CAAC;uBAmBK,cAAc,KAAG,OAAO,CAAC,eAAe,CAAC;mCAuB7D,eAAe,YACf,aAAa,KACtB,OAAO,CAAC,YAAY,CAAC;iCAmBV,MAAM,WACT,WAAW,KACnB,OAAO,CAAC,eAAe,CAAC;oCAuBb,MAAM,WACT,WAAW,KACnB,OAAO,CAAC,eAAe,CAAC;;;EA2C5B"}
1
+ {"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../../../src/adapters/vue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAkB9D,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EAET,WAAW,EACZ,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC3E,YAAY,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EACZ,eAAe,EACf,sBAAsB,EACtB,yBAAyB,EACzB,SAAS,EACT,cAAc,EACd,WAAW,EACX,OAAO,EACP,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAMvB,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,GAAG,OAAO,CAAC;AAM/F;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;4BAiBnC,cAAc,YACb,aAAa,KACtB,OAAO,CAAC,eAAe,CAAC;uBAuBK,cAAc,KAAG,OAAO,CAAC,eAAe,CAAC;mCA6B7D,eAAe,YACf,aAAa,KACtB,OAAO,CAAC,YAAY,CAAC;iCAuBV,MAAM,WACT,WAAW,KACnB,OAAO,CAAC,eAAe,CAAC;oCA0Bb,MAAM,WACT,WAAW,KACnB,OAAO,CAAC,eAAe,CAAC;;;EA8C5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/client/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAM5C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6ED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,GAAE,YAAiB,GAAG,MAAM,CAwC9D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC;AAMD,YAAY,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/client/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAM5C;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6ED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,MAAM,GAAE,YAAiB,GAAG,MAAM,CA0C9D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC;AAMD,YAAY,EAAE,MAAM,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"phone-auth-client.d.ts","sourceRoot":"","sources":["../../../src/client/phone-auth-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EAEZ,WAAW,EAEX,sBAAsB,EAEtB,yBAAyB,EACzB,eAAe,EAShB,MAAM,eAAe,CAAC;AAyDvB,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,GAAE,UAAe;IA+CnC;;;;;;;;;;;;;;;;OAgBG;IACG,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC;IAoC9F;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAgEhE;;;;;;;;;;OAUG;IACG,kBAAkB,CACtB,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC;IAuBxB;;OAEG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC;IAuBlC;;OAEG;IACG,iBAAiB,CACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,yBAAyB,CAAC;IA2BrC;;OAEG;IACH,WAAW,IAAI,OAAO;IAKtB;;OAEG;IACH,qBAAqB,IAAI;QACvB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;IA4BD;;OAEG;YACW,UAAU;IAwGxB;;;OAGG;IACH,OAAO,CAAC,UAAU;IA0DlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgGrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAG1B"}
1
+ {"version":3,"file":"phone-auth-client.d.ts","sourceRoot":"","sources":["../../../src/client/phone-auth-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,eAAe,EACf,aAAa,EACb,YAAY,EAEZ,WAAW,EAEX,sBAAsB,EAEtB,yBAAyB,EACzB,eAAe,EAShB,MAAM,eAAe,CAAC;AAyDvB,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,GAAE,UAAe;IA+CnC;;;;;;;;;;;;;;;;OAgBG;IACG,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC;IA2C9F;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAiEhE;;;;;;;;;;OAUG;IACG,kBAAkB,CACtB,QAAQ,EAAE,eAAe,EACzB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC;IAuBxB;;OAEG;IACG,cAAc,CAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,sBAAsB,CAAC;IA0BlC;;OAEG;IACG,iBAAiB,CACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,yBAAyB,CAAC;IA2BrC;;OAEG;IACH,WAAW,IAAI,OAAO;IAKtB;;OAEG;IACH,qBAAqB,IAAI;QACvB,SAAS,EAAE,OAAO,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;IA4BD;;OAEG;YACW,UAAU;IAiIxB;;;OAGG;IACH,OAAO,CAAC,UAAU;IA8DlB;;OAEG;IACH,OAAO,CAAC,aAAa;IAoGrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;CAG1B"}
@@ -47,9 +47,11 @@ export declare function getUserMessage(error: AuthError): string;
47
47
  * @example
48
48
  * ```typescript
49
49
  * throw createAuthError('INVALID_PHONE_NUMBER', 'Phone number must start with +');
50
+ * // With original error preserved:
51
+ * throw createAuthError('USER_CANCELLED', 'User cancelled', undefined, originalError);
50
52
  * ```
51
53
  */
52
- export declare function createAuthError(code: ErrorCode, message?: string, details?: unknown): AuthError;
54
+ export declare function createAuthError(code: ErrorCode, message?: string, details?: unknown, cause?: Error): AuthError;
53
55
  /**
54
56
  * Create a client-side AuthError with context.
55
57
  */
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAMlD;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;CAqBd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AA2BrE;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAS9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAOvD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,OAAO,GAChB,SAAS,CAMX;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GACA,SAAS,CAUX;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAwC9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAexE"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAMlD;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;CAqBd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,OAAO,WAAW,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AA2BrE;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAS9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE1D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAOvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,OAAO,EACjB,KAAK,CAAC,EAAE,KAAK,GACZ,SAAS,CAgBX;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,SAAS,EACf,OAAO,EAAE;IACP,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GACA,SAAS,CAUX;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAwC9D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAexE"}
@@ -32,12 +32,12 @@ export type AuthenticationStrategy = typeof AUTHENTICATION_STRATEGY[keyof typeof
32
32
  export interface SessionInfo {
33
33
  /** Unique session identifier */
34
34
  session_key: string;
35
- /** Use case for this session (returned by server) */
36
- use_case?: UseCase;
37
35
  /** Security nonce */
38
36
  nonce?: string;
39
- /** Additional metadata from server */
37
+ /** Additional metadata from server (includes use_case, challenge info, etc.) */
40
38
  metadata?: Record<string, string>;
39
+ /** Protocol type: "ts43", "link", "desktop", etc. */
40
+ protocol_type?: string;
41
41
  }
42
42
  /**
43
43
  * Public Land Mobile Network identifiers.
@@ -487,6 +487,8 @@ export interface AuthError extends Error {
487
487
  traceId?: string;
488
488
  spanId?: string;
489
489
  service?: string;
490
+ /** Original error that caused this error (preserves stack trace) */
491
+ cause?: Error;
490
492
  /** Browser error details (for Digital Credentials API errors) */
491
493
  browserError?: {
492
494
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../src/test/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,eAAe,CAAC;AAOvB,eAAO,MAAM,YAAY,EAAE,WAK1B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,WAE5B,CAAC;AAMF,eAAO,MAAM,aAAa,EAAE,QAqB3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,eAI/B,CAAC;AAMF,eAAO,MAAM,aAAa,EAAE,QAK3B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,QAE7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,eAI/B,CAAC;AAMF,eAAO,MAAM,gBAAgB,EAAE,WAc9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,WAIhC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAIlC,CAAC;AAMF,eAAO,MAAM,iBAAiB,EAAE,YAI/B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,YAKrC,CAAC;AAMF,eAAO,MAAM,mBAAmB,EAAE,cAKjC,CAAC;AAMF,eAAO,MAAM,2BAA2B,EAAE,sBAGzC,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,yBAI5C,CAAC;AAMF,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAMF,eAAO,MAAM,oBAAoB;;;;;;;;CAQhC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;CAKjC,CAAC;AAEF,eAAO,MAAM,mBAAmB;;CAE/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAE5D,eAAO,MAAM,mBAAmB,UAAuB,CAAC;AAExD,eAAO,MAAM,kBAAkB,MAAO,CAAC;AAMvC;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,OAQzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,OAIjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oCAAoC;;;CAGhD,CAAC;AAEF,eAAO,MAAM,kCAAkC;;;CAG9C,CAAC;AAEF,eAAO,MAAM,iCAAiC;;;CAG7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;CAU/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAO7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;CAOvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;CAMrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;CAKvB,CAAC"}
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../src/test/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EACd,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,eAAe,CAAC;AAOvB,eAAO,MAAM,YAAY,EAAE,WAO1B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,WAE5B,CAAC;AAMF,eAAO,MAAM,aAAa,EAAE,QAqB3B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,eAI/B,CAAC;AAMF,eAAO,MAAM,aAAa,EAAE,QAK3B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,QAE7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,eAI/B,CAAC;AAMF,eAAO,MAAM,gBAAgB,EAAE,WAc9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,WAIhC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAIlC,CAAC;AAMF,eAAO,MAAM,iBAAiB,EAAE,YAI/B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,YAKrC,CAAC;AAMF,eAAO,MAAM,mBAAmB,EAAE,cAKjC,CAAC;AAMF,eAAO,MAAM,2BAA2B,EAAE,sBAGzC,CAAC;AAEF,eAAO,MAAM,8BAA8B,EAAE,yBAI5C,CAAC;AAMF,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;CAIlC,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;CAGhC,CAAC;AAEF,eAAO,MAAM,kBAAkB;;;;CAI9B,CAAC;AAMF,eAAO,MAAM,oBAAoB;;;;;;;;CAQhC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;CAKjC,CAAC;AAEF,eAAO,MAAM,mBAAmB;;CAE/B,CAAC;AAEF,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAE5D,eAAO,MAAM,mBAAmB,UAAuB,CAAC;AAExD,eAAO,MAAM,kBAAkB,MAAO,CAAC;AAMvC;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,OAQzC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,OAIjC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oCAAoC;;;CAGhD,CAAC;AAEF,eAAO,MAAM,kCAAkC;;;CAG9C,CAAC;AAEF,eAAO,MAAM,iCAAiC;;;CAG7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;CAU/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;CAO7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;CAOvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;CAMrB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;CAKvB,CAAC"}
@@ -27,6 +27,7 @@ export declare function advanceTimersAndFlush(ms: number): Promise<void>;
27
27
  * Create spies on console methods for logger tests.
28
28
  */
29
29
  export declare function createConsoleMocks(): {
30
+ log: jest.SpyInstance<void, [message?: any, ...optionalParams: any[]], any>;
30
31
  debug: jest.SpyInstance<void, [message?: any, ...optionalParams: any[]], any>;
31
32
  info: jest.SpyInstance<void, [message?: any, ...optionalParams: any[]], any>;
32
33
  warn: jest.SpyInstance<void, [message?: any, ...optionalParams: any[]], any>;
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/test/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,2BAA2B,CAAC;AAmCnC;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAChF,QAAQ,CAqBV;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAMD;;GAEG;AACH,wBAAgB,kBAAkB;;;;;EAOjC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,QAK/E"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../src/test/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,2BAA2B,CAAC;AAmCnC;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,EACb,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAO,GAChF,QAAQ,CAqBV;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAMD;;GAEG;AACH,wBAAgB,kBAAkB;;;;;;EAQjC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,QAM/E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glideidentity/web-client-sdk",
3
- "version": "6.0.1",
3
+ "version": "6.0.2",
4
4
  "description": "Glide Phone Authentication SDK for web applications",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -51,7 +51,8 @@
51
51
  "clean": "rm -rf dist",
52
52
  "prepublishOnly": "npm run build",
53
53
  "test": "jest",
54
- "typecheck": "tsc --noEmit -p tsconfig.json"
54
+ "typecheck": "tsc --noEmit -p tsconfig.json",
55
+ "release": "./scripts/publish.sh"
55
56
  },
56
57
  "publishConfig": {
57
58
  "access": "public"