@pelican-identity/vanilla 1.0.13 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.min.js CHANGED
@@ -5,7 +5,7 @@ Make sure your charset is UTF-8`);i=(i>>>8&255)*192+(i&255),n.put(i,13);}};Bn.ex
5
5
  The chosen QR Code version cannot contain this amount of data.
6
6
  Minimum version required to store current data is: `+u+`.
7
7
  `);let p=tf(e,i,l),y=Ne.getSymbolSize(e),E=new Fi(y);return Ji(E,e),Zi(E),Qi(E,e),yr(E,i,0),e>=7&&Gi(E,e),Xi(E,p),isNaN(a)&&(a=br.getBestMask(E,yr.bind(null,E,i))),br.applyMask(a,E),yr(E,i,a),{modules:E,version:e,errorCorrectionLevel:i,maskPattern:a,segments:l}}jn.create=function(e,i){if(typeof e>"u"||e==="")throw new Error("No input text");let a=gr.M,l,u;return typeof i<"u"&&(a=gr.from(i.errorCorrectionLevel,gr.M),l=Pe.from(i.version),u=br.from(i.maskPattern),i.toSJISFunc&&Ne.setToSJISFunction(i.toSJISFunc)),rf(e,l,a,u)};});var mr=rt(Kt=>{function On(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let e=n.slice().replace("#","").split("");if(e.length<3||e.length===5||e.length>8)throw new Error("Invalid hex color: "+n);(e.length===3||e.length===4)&&(e=Array.prototype.concat.apply([],e.map(function(a){return [a,a]}))),e.length===6&&e.push("F","F");let i=parseInt(e.join(""),16);return {r:i>>24&255,g:i>>16&255,b:i>>8&255,a:i&255,hex:"#"+e.slice(0,6).join("")}}Kt.getOptions=function(e){e||(e={}),e.color||(e.color={});let i=typeof e.margin>"u"||e.margin===null||e.margin<0?4:e.margin,a=e.width&&e.width>=21?e.width:void 0,l=e.scale||4;return {width:a,scale:a?4:l,margin:i,color:{dark:On(e.color.dark||"#000000ff"),light:On(e.color.light||"#ffffffff")},type:e.type,rendererOpts:e.rendererOpts||{}}};Kt.getScale=function(e,i){return i.width&&i.width>=e+i.margin*2?i.width/(e+i.margin*2):i.scale};Kt.getImageWidth=function(e,i){let a=Kt.getScale(e,i);return Math.floor((e+i.margin*2)*a)};Kt.qrToImageData=function(e,i,a){let l=i.modules.size,u=i.modules.data,p=Kt.getScale(l,a),y=Math.floor((l+a.margin*2)*p),E=a.margin*p,V=[a.color.light,a.color.dark];for(let $=0;$<y;$++)for(let lt=0;lt<y;lt++){let it=($*y+lt)*4,wt=a.color.light;if($>=E&&lt>=E&&$<y-E&&lt<y-E){let mt=Math.floor(($-E)/p),vt=Math.floor((lt-E)/p);wt=V[u[mt*l+vt]?1:0];}e[it++]=wt.r,e[it++]=wt.g,e[it++]=wt.b,e[it]=wt.a;}};});var qn=rt(ke=>{var vr=mr();function nf(n,e,i){n.clearRect(0,0,e.width,e.height),e.style||(e.style={}),e.height=i,e.width=i,e.style.height=i+"px",e.style.width=i+"px";}function ff(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}ke.render=function(e,i,a){let l=a,u=i;typeof l>"u"&&(!i||!i.getContext)&&(l=i,i=void 0),i||(u=ff()),l=vr.getOptions(l);let p=vr.getImageWidth(e.modules.size,l),y=u.getContext("2d"),E=y.createImageData(p,p);return vr.qrToImageData(E.data,e,l),nf(y,u,p),y.putImageData(E,0,0),u};ke.renderToDataURL=function(e,i,a){let l=a;typeof l>"u"&&(!i||!i.getContext)&&(l=i,i=void 0),l||(l={});let u=ke.render(e,i,l),p=l.type||"image/png",y=l.rendererOpts||{};return u.toDataURL(p,y.quality)};});var Kn=rt(Fn=>{var of=mr();function Yn(n,e){let i=n.a/255,a=e+'="'+n.hex+'"';return i<1?a+" "+e+'-opacity="'+i.toFixed(2).slice(1)+'"':a}function Cr(n,e,i){let a=n+e;return typeof i<"u"&&(a+=" "+i),a}function sf(n,e,i){let a="",l=0,u=false,p=0;for(let y=0;y<n.length;y++){let E=Math.floor(y%e),V=Math.floor(y/e);!E&&!u&&(u=true),n[y]?(p++,y>0&&E>0&&n[y-1]||(a+=u?Cr("M",E+i,.5+V+i):Cr("m",l,0),l=0,u=false),E+1<e&&n[y+1]||(a+=Cr("h",p),p=0)):l++;}return a}Fn.render=function(e,i,a){let l=of.getOptions(i),u=e.modules.size,p=e.modules.data,y=u+l.margin*2,E=l.color.light.a?"<path "+Yn(l.color.light,"fill")+' d="M0 0h'+y+"v"+y+'H0z"/>':"",V="<path "+Yn(l.color.dark,"stroke")+' d="'+sf(p,u,l.margin)+'"/>',$='viewBox="0 0 '+y+" "+y+'"',it='<svg xmlns="http://www.w3.org/2000/svg" '+(l.width?'width="'+l.width+'" height="'+l.width+'" ':"")+$+' shape-rendering="crispEdges">'+E+V+`</svg>
8
- `;return typeof a=="function"&&a(null,it),it};});var Hn=rt(xe=>{var af=Vr(),Er=Dn(),$n=qn(),cf=Kn();function Ar(n,e,i,a,l){let u=[].slice.call(arguments,1),p=u.length,y=typeof u[p-1]=="function";if(!y&&!af())throw new Error("Callback required as last argument");if(y){if(p<2)throw new Error("Too few arguments provided");p===2?(l=i,i=e,e=a=void 0):p===3&&(e.getContext&&typeof l>"u"?(l=a,a=void 0):(l=a,a=i,i=e,e=void 0));}else {if(p<1)throw new Error("Too few arguments provided");return p===1?(i=e,e=a=void 0):p===2&&!e.getContext&&(a=i,i=e,e=void 0),new Promise(function(E,V){try{let $=Er.create(i,a);E(n($,e,a));}catch($){V($);}})}try{let E=Er.create(i,a);l(null,n(E,e,a));}catch(E){l(E);}}xe.create=Er.create;xe.toCanvas=Ar.bind(null,$n.render);xe.toDataURL=Ar.bind(null,$n.renderToDataURL);xe.toString=Ar.bind(null,function(n,e,i){return cf.render(n,i)});});var Xn=rt(Mt=>{var lf=Fr(),$t=$r(),uf=Hn();function Vn(n){return n&&n.__esModule?n:{default:n}}var ze=Vn(lf),hf=Vn(uf),Wn=class{generateSymmetricKey(){let n=ze.default.randomBytes(32);return $t.encodeBase64(n)}encryptSymmetric({plaintext:n,keyString:e}){let i=$t.decodeBase64(e),a=ze.default.randomBytes(24),l=new TextEncoder().encode(n),u=ze.default.secretbox(l,a,i);return {cipher:$t.encodeBase64(u),nonce:$t.encodeBase64(a)}}decryptSymmetric({encrypted:n,keyString:e}){try{let i=$t.decodeBase64(e),a=$t.decodeBase64(n.cipher),l=$t.decodeBase64(n.nonce),u=ze.default.secretbox.open(a,l,i);if(!u)throw new Error("Decryption failed - invalid key or corrupted data");return new TextDecoder().decode(u)}catch(i){return console.error("Decryption failed",i),null}}},df=Wn,xf=class{constructor(){this.prefix="pelican_auth_",this.defaultTTL=300*1e3,this.memoryCache=new Map;}set(n,e,i={}){let{ttlMs:a=this.defaultTTL,useSessionStorage:l=true}=i,u=Date.now()+a,p={value:e,expiresAt:u};if(l)try{sessionStorage.setItem(`${this.prefix}${n}`,JSON.stringify(p));}catch(y){console.warn("SessionStorage unavailable, using memory:",y),this.setMemory(n,p);}else this.setMemory(n,p);}get(n){try{let e=sessionStorage.getItem(`${this.prefix}${n}`);if(e){let i=JSON.parse(e);return Date.now()>i.expiresAt?(this.remove(n),null):i.value}}catch{}return this.getMemory(n)}remove(n){try{sessionStorage.removeItem(`${this.prefix}${n}`);}catch{}this.memoryCache.delete(n);}clear(){try{Object.keys(sessionStorage).forEach(n=>{n.startsWith(this.prefix)&&sessionStorage.removeItem(n);});}catch{}this.memoryCache.clear();}setMemory(n,e){this.memoryCache.set(n,e);let i=e.expiresAt-Date.now();setTimeout(()=>{this.memoryCache.delete(n);},i);}getMemory(n){let e=this.memoryCache.get(n);return e?Date.now()>e.expiresAt?(this.memoryCache.delete(n),null):e.value:null}},De=new xf,Jn=(n,e,i)=>{De.set("session",{sessionId:n,sessionKey:e},{ttlMs:i});},Zn=()=>De.get("session"),je=()=>{De.remove("session");},gf=()=>{De.clear();},Qn=class{constructor(){this.state="idle",this.listeners=new Set;}get current(){return this.state}transition(n){this.state=n,this.listeners.forEach(e=>e(n));}subscribe(n){return this.listeners.add(n),()=>this.listeners.delete(n)}},Gn=class{constructor(n){this.reconnectAttempts=0,this.maxReconnectAttempts=3,this.isExplicitlyClosed=false,this.isReconnecting=false,this.handlers=n;}connect(n){this.url=n,this.isExplicitlyClosed=false,this.socket&&(this.socket.onclose=null,this.socket.onerror=null,this.socket.onmessage=null,this.socket.onopen=null,(this.socket.readyState===WebSocket.OPEN||this.socket.readyState===WebSocket.CONNECTING)&&this.socket.close()),this.socket=new WebSocket(n),this.socket.onopen=()=>{this.reconnectAttempts=0,this.isReconnecting=false,this.handlers.onOpen?.();},this.socket.onmessage=e=>{try{let i=JSON.parse(e.data);this.handlers.onMessage?.(i);}catch(i){console.error("Failed to parse WebSocket message",i);}},this.socket.onerror=e=>{!this.isReconnecting&&!this.isExplicitlyClosed&&this.handlers.onError?.(e);},this.socket.onclose=e=>{this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0),this.isReconnecting||this.handlers.onClose?.(e),!this.isExplicitlyClosed&&!this.isReconnecting&&this.reconnectAttempts<this.maxReconnectAttempts&&this.attemptReconnect();};}attemptReconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts){console.warn("Max WebSocket reconnect attempts reached");return}this.isReconnecting=true,this.reconnectAttempts++;let n=Math.min(Math.pow(2,this.reconnectAttempts-1)*500,2e3);console.log(`Reconnecting WebSocket (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}) in ${n}ms...`),this.reconnectTimeout=window.setTimeout(()=>{this.url&&!this.isExplicitlyClosed&&this.connect(this.url);},n);}send(n){if(this.socket?.readyState===WebSocket.OPEN)try{this.socket.send(JSON.stringify(n));}catch(e){console.error("Failed to send WebSocket message:",e);}else console.warn("WebSocket not open, message not sent:",this.socket?.readyState);}close(){this.isExplicitlyClosed=true,this.isReconnecting=false,this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0),this.socket&&(this.socket.onclose=null,this.socket.onerror=null,this.socket.onmessage=null,this.socket.onopen=null,(this.socket.readyState===WebSocket.OPEN||this.socket.readyState===WebSocket.CONNECTING)&&this.socket.close(),this.socket=void 0);}get readyState(){return this.socket?.readyState}get isOpen(){return this.socket?.readyState===WebSocket.OPEN}},Sr="https://identityapi.pelicanidentity.com",pf=class{constructor(n){if(this.crypto=new df,this.stateMachine=new Qn,this.sessionId="",this.sessionKey=null,this.useWebSocket=true,this.listeners={},!n.publicKey)throw new Error("Missing publicKey");if(!n.projectId)throw new Error("Missing projectId");if(!n.authType)throw new Error("Missing authType");this.config={continuousMode:false,forceQRCode:false,...n},this.stateMachine.subscribe(e=>this.emit("state",e)),this.attachVisibilityRecovery();}on(n,e){var i;return (i=this.listeners)[n]??(i[n]=new Set),this.listeners[n].add(e),()=>this.listeners[n].delete(e)}async start(){if(this.stateMachine.current==="idle"){this.resetSession(),je(),this.stateMachine.transition("initializing");try{this.sessionKey=this.crypto.generateSymmetricKey(),this.sessionId=crypto.randomUUID()+crypto.randomUUID(),this.useWebSocket=this.shouldUseWebSocket(),this.useWebSocket?await this.startWebSocketFlow():await this.startDeepLinkFlow();}catch(n){this.fail(n instanceof Error?n:new Error("Start failed"));}}}stop(){this.terminate(false);}destroy(){this.detachVisibilityRecovery(),this.clearBackupCheck(),this.transport?.close(),this.transport=void 0,this.listeners={};}useQrInstead(){this.useWebSocket=true,this.emit("deeplink",""),this.stateMachine.transition("initializing"),this.startWebSocketFlow();}useDeepLinkInstead(){this.useWebSocket=false,this.stateMachine.transition("initializing"),this.startDeepLinkFlow();}shouldUseWebSocket(){let n=navigator.userAgent,e=/(iPad|Android(?!.*Mobile))/i.test(n),a=/Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(n)&&!e;return this.config.forceQRCode||!a}async startWebSocketFlow(){let n=await this.fetchRelayUrl(true);this.transport=new Gn({onOpen:()=>{this.transport.send({type:"register",sessionID:this.sessionId,...this.config}),this.stateMachine.transition("awaiting-pair");},onMessage:e=>this.handleWebSocketMessage(e),onError:e=>{console.error("WebSocket error:",e),this.fail(new Error("WebSocket connection failed"));}}),this.transport.connect(n),await this.emitQRCode();}handleWebSocketMessage(n){switch(n.type){case "paired":this.stateMachine.transition("paired"),this.transport.send({type:"authenticate",sessionID:this.sessionId,...this.config,url:window.location.href});return;case "phone-auth-success":this.handleAuthSuccess(n);return;case "phone-terminated":this.fail(new Error("Authentication cancelled on device")),this.restartIfContinuous();return;case "confirmed":this.terminate(true),this.restartIfContinuous();return}}handleAuthSuccess(n){if(!this.sessionKey||!n.cipher||!n.nonce){this.fail(new Error("Invalid authentication payload")),this.restartIfContinuous();return}try{let e=this.crypto.decryptSymmetric({encrypted:{cipher:n.cipher,nonce:n.nonce},keyString:this.sessionKey});if(!e){this.fail(new Error("Invalid authentication data")),this.restartIfContinuous();return}let i=JSON.parse(e);this.emit("success",i),this.stateMachine.transition("authenticated"),this.transport?.send({type:"confirm",sessionID:this.sessionId});}catch{this.fail(new Error("Failed to decrypt authentication data")),this.restartIfContinuous();}}async startDeepLinkFlow(){let n=await this.fetchRelayUrl(false);this.sessionKey&&Jn(this.sessionId,this.sessionKey,10*6e4),await this.emitDeepLink(n),this.stateMachine.transition("awaiting-pair");}clearBackupCheck(){this.backupCheckTimeout&&(clearTimeout(this.backupCheckTimeout),this.backupCheckTimeout=void 0);}async checkSession(){let n=Zn();if(n){this.stateMachine.transition("awaiting-auth");try{let e=await fetch(`${Sr}/session?session_id=${n.sessionId}`);if(!e.ok)return;let i=await e.json(),a=this.crypto.decryptSymmetric({encrypted:{cipher:i.cipher,nonce:i.nonce},keyString:n.sessionKey});if(!a){console.warn("Failed to decrypt session");return}let l=JSON.parse(a);this.clearBackupCheck(),je(),this.emit("success",l),this.stateMachine.transition("authenticated"),this.config.continuousMode?setTimeout(()=>{this.stateMachine.transition("idle"),this.start();},1500):this.stateMachine.transition("idle");}catch(e){console.debug("Session check failed:",e);}}}async emitQRCode(){let n={sessionID:this.sessionId,sessionKey:this.sessionKey,publicKey:this.config.publicKey,authType:this.config.authType,projectId:this.config.projectId,url:window.location.href},e=await hf.default.toDataURL(JSON.stringify(n),{type:"image/png",scale:3,color:{light:"#ffffff",dark:"#424242ff"}});this.emit("qr",e);}async emitDeepLink(n){let e=`${n}?sessionID=${encodeURIComponent(this.sessionId)}&sessionKey=${encodeURIComponent(this.sessionKey)}&publicKey=${encodeURIComponent(this.config.publicKey)}&authType=${this.config.authType}&projectId=${encodeURIComponent(this.config.projectId)}&url=${encodeURIComponent(n)}`;this.emit("deeplink",e);}attachVisibilityRecovery(){this.visibilityHandler=async()=>{document.visibilityState==="visible"&&(this.useWebSocket||await this.checkSession());},document.addEventListener("visibilitychange",this.visibilityHandler);}detachVisibilityRecovery(){this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=void 0);}async fetchRelayUrl(n){let{publicKey:e,projectId:i,authType:a}=this.config,l=await fetch(`${Sr}/relay?public_key=${e}&auth_type=${a}&project_id=${i}`);if(!l.ok){let p=await l.text();throw new Error(p)}let u=await l.json();return n?u.relay_url:u.deeplink_url}terminate(n){this.clearBackupCheck(),this.transport&&(n||this.transport.send({type:"client-terminated",sessionID:this.sessionId,projectId:this.config.projectId,publicKey:this.config.publicKey,authType:this.config.authType}),this.transport.close(),this.transport=void 0),je(),this.resetSession(),this.config.continuousMode||this.detachVisibilityRecovery(),this.stateMachine.transition(n?"confirmed":"idle");}restartIfContinuous(){this.stateMachine.transition("idle"),this.clearBackupCheck(),this.transport?.close(),this.transport=void 0,this.config.continuousMode&&setTimeout(()=>{this.start();},150);}resetSession(){this.sessionId="",this.sessionKey=null;}emit(n,e){this.listeners[n]?.forEach(i=>i(e));}fail(n){this.emit("error",n),this.stateMachine.transition("error");}};Mt.BASEURL=Sr;Mt.CryptoService=Wn;Mt.PelicanAuthentication=pf;Mt.StateMachine=Qn;Mt.Transport=Gn;Mt.clearAllAuthData=gf;Mt.clearAuthSession=je;Mt.getAuthSession=Zn;Mt.storeAuthSession=Jn;});var ti=gi(Xn());function yf(){if(document.getElementById("pelican-auth-styles"))return;let n=document.createElement("style");n.id="pelican-auth-styles",n.textContent=`@keyframes fadeUp {
8
+ `;return typeof a=="function"&&a(null,it),it};});var Hn=rt(xe=>{var af=Vr(),Er=Dn(),$n=qn(),cf=Kn();function Ar(n,e,i,a,l){let u=[].slice.call(arguments,1),p=u.length,y=typeof u[p-1]=="function";if(!y&&!af())throw new Error("Callback required as last argument");if(y){if(p<2)throw new Error("Too few arguments provided");p===2?(l=i,i=e,e=a=void 0):p===3&&(e.getContext&&typeof l>"u"?(l=a,a=void 0):(l=a,a=i,i=e,e=void 0));}else {if(p<1)throw new Error("Too few arguments provided");return p===1?(i=e,e=a=void 0):p===2&&!e.getContext&&(a=i,i=e,e=void 0),new Promise(function(E,V){try{let $=Er.create(i,a);E(n($,e,a));}catch($){V($);}})}try{let E=Er.create(i,a);l(null,n(E,e,a));}catch(E){l(E);}}xe.create=Er.create;xe.toCanvas=Ar.bind(null,$n.render);xe.toDataURL=Ar.bind(null,$n.renderToDataURL);xe.toString=Ar.bind(null,function(n,e,i){return cf.render(n,i)});});var Xn=rt(Mt=>{var lf=Fr(),$t=$r(),uf=Hn();function Vn(n){return n&&n.__esModule?n:{default:n}}var ze=Vn(lf),hf=Vn(uf),Wn=class{generateSymmetricKey(){let n=ze.default.randomBytes(32);return $t.encodeBase64(n)}encryptSymmetric({plaintext:n,keyString:e}){let i=$t.decodeBase64(e),a=ze.default.randomBytes(24),l=new TextEncoder().encode(n),u=ze.default.secretbox(l,a,i);return {cipher:$t.encodeBase64(u),nonce:$t.encodeBase64(a)}}decryptSymmetric({encrypted:n,keyString:e}){try{let i=$t.decodeBase64(e),a=$t.decodeBase64(n.cipher),l=$t.decodeBase64(n.nonce),u=ze.default.secretbox.open(a,l,i);if(!u)throw new Error("Decryption failed - invalid key or corrupted data");return new TextDecoder().decode(u)}catch(i){return console.error("Decryption failed",i),null}}},df=Wn,xf=class{constructor(){this.prefix="pelican_auth_",this.defaultTTL=300*1e3,this.memoryCache=new Map;}set(n,e,i={}){let{ttlMs:a=this.defaultTTL,useSessionStorage:l=true}=i,u=Date.now()+a,p={value:e,expiresAt:u};if(l)try{sessionStorage.setItem(`${this.prefix}${n}`,JSON.stringify(p));}catch(y){console.warn("SessionStorage unavailable, using memory:",y),this.setMemory(n,p);}else this.setMemory(n,p);}get(n){try{let e=sessionStorage.getItem(`${this.prefix}${n}`);if(e){let i=JSON.parse(e);return Date.now()>i.expiresAt?(this.remove(n),null):i.value}}catch{}return this.getMemory(n)}remove(n){try{sessionStorage.removeItem(`${this.prefix}${n}`);}catch{}this.memoryCache.delete(n);}clear(){try{Object.keys(sessionStorage).forEach(n=>{n.startsWith(this.prefix)&&sessionStorage.removeItem(n);});}catch{}this.memoryCache.clear();}setMemory(n,e){this.memoryCache.set(n,e);let i=e.expiresAt-Date.now();setTimeout(()=>{this.memoryCache.delete(n);},i);}getMemory(n){let e=this.memoryCache.get(n);return e?Date.now()>e.expiresAt?(this.memoryCache.delete(n),null):e.value:null}},De=new xf,Jn=(n,e,i)=>{De.set("session",{sessionId:n,sessionKey:e},{ttlMs:i});},Zn=()=>De.get("session"),je=()=>{De.remove("session");},gf=()=>{De.clear();},Qn=class{constructor(){this.state="idle",this.listeners=new Set;}get current(){return this.state}transition(n){this.state=n,this.listeners.forEach(e=>e(n));}subscribe(n){return this.listeners.add(n),()=>this.listeners.delete(n)}},Gn=class{constructor(n){this.reconnectAttempts=0,this.maxReconnectAttempts=3,this.isExplicitlyClosed=false,this.isReconnecting=false,this.handlers=n;}connect(n){this.url=n,this.isExplicitlyClosed=false,this.socket&&(this.socket.onclose=null,this.socket.onerror=null,this.socket.onmessage=null,this.socket.onopen=null,(this.socket.readyState===WebSocket.OPEN||this.socket.readyState===WebSocket.CONNECTING)&&this.socket.close()),this.socket=new WebSocket(n),this.socket.onopen=()=>{this.reconnectAttempts=0,this.isReconnecting=false,this.handlers.onOpen?.();},this.socket.onmessage=e=>{try{let i=JSON.parse(e.data);this.handlers.onMessage?.(i);}catch(i){console.error("Failed to parse WebSocket message",i);}},this.socket.onerror=e=>{!this.isReconnecting&&!this.isExplicitlyClosed&&this.handlers.onError?.(e);},this.socket.onclose=e=>{this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0),this.isReconnecting||this.handlers.onClose?.(e),!this.isExplicitlyClosed&&!this.isReconnecting&&this.reconnectAttempts<this.maxReconnectAttempts&&this.attemptReconnect();};}attemptReconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts){console.warn("Max WebSocket reconnect attempts reached");return}this.isReconnecting=true,this.reconnectAttempts++;let n=Math.min(Math.pow(2,this.reconnectAttempts-1)*500,2e3);console.log(`Reconnecting WebSocket (attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts}) in ${n}ms...`),this.reconnectTimeout=window.setTimeout(()=>{this.url&&!this.isExplicitlyClosed&&this.connect(this.url);},n);}send(n){if(this.socket?.readyState===WebSocket.OPEN)try{this.socket.send(JSON.stringify(n));}catch(e){console.error("Failed to send WebSocket message:",e);}else console.warn("WebSocket not open, message not sent:",this.socket?.readyState);}close(){this.isExplicitlyClosed=true,this.isReconnecting=false,this.reconnectTimeout&&(clearTimeout(this.reconnectTimeout),this.reconnectTimeout=void 0),this.socket&&(this.socket.onclose=null,this.socket.onerror=null,this.socket.onmessage=null,this.socket.onopen=null,(this.socket.readyState===WebSocket.OPEN||this.socket.readyState===WebSocket.CONNECTING)&&this.socket.close(),this.socket=void 0);}get readyState(){return this.socket?.readyState}get isOpen(){return this.socket?.readyState===WebSocket.OPEN}},Sr="https://identityapi.pelicanidentity.com",pf=class{constructor(n){if(this.crypto=new df,this.stateMachine=new Qn,this.sessionId="",this.sessionKey=null,this.useWebSocket=true,this.listeners={},!n.publicKey)throw new Error("Missing publicKey");if(!n.projectId)throw new Error("Missing projectId");if(!n.authType)throw new Error("Missing authType");this.config={continuousMode:false,forceQRCode:false,...n},this.stateMachine.subscribe(e=>this.emit("state",e)),this.attachVisibilityRecovery();}on(n,e){var i;return (i=this.listeners)[n]??(i[n]=new Set),this.listeners[n].add(e),()=>this.listeners[n].delete(e)}async start(){if(this.stateMachine.current==="idle"){this.resetSession(),je(),this.stateMachine.transition("initializing");try{this.sessionKey=this.crypto.generateSymmetricKey(),this.sessionId=crypto.randomUUID()+crypto.randomUUID(),this.useWebSocket=this.shouldUseWebSocket(),this.useWebSocket?await this.startWebSocketFlow():await this.startDeepLinkFlow();}catch(n){this.fail(n instanceof Error?n:new Error("Start failed"));}}}stop(){this.terminate(false);}destroy(){this.detachVisibilityRecovery(),this.clearBackupCheck(),this.transport?.close(),this.transport=void 0,this.listeners={};}useQrInstead(){this.useWebSocket=true,this.emit("deeplink",""),this.stateMachine.transition("initializing"),this.startWebSocketFlow();}useDeepLinkInstead(){this.useWebSocket=false,this.stateMachine.transition("initializing"),this.startDeepLinkFlow();}shouldUseWebSocket(){let n=navigator.userAgent,e=/(iPad|Android(?!.*Mobile))/i.test(n),a=/Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(n)&&!e;return this.config.forceQRCode||!a}async startWebSocketFlow(){let n=await this.fetchRelayUrl(true);this.transport=new Gn({onOpen:()=>{this.transport.send({type:"register",sessionID:this.sessionId,...this.config}),this.stateMachine.transition("awaiting-pair");},onMessage:e=>this.handleWebSocketMessage(e),onError:e=>{console.error("WebSocket error:",e),this.fail(new Error("WebSocket connection failed"));}}),this.transport.connect(n),await this.emitQRCode();}handleWebSocketMessage(n){switch(n.type){case "paired":this.stateMachine.transition("paired"),this.transport.send({type:"authenticate",sessionID:this.sessionId,...this.config,url:window.location.href});return;case "phone-auth-success":this.handleAuthSuccess(n);return;case "phone-terminated":this.fail(new Error("Authentication cancelled on device")),this.restartIfContinuous();return;case "confirmed":this.terminate(true),this.restartIfContinuous();return}}handleAuthSuccess(n){if(!this.sessionKey||!n.cipher||!n.nonce){this.fail(new Error("Invalid authentication payload")),this.restartIfContinuous();return}try{let e=this.crypto.decryptSymmetric({encrypted:{cipher:n.cipher,nonce:n.nonce},keyString:this.sessionKey});if(!e){this.fail(new Error("Invalid authentication data")),this.restartIfContinuous();return}let i=JSON.parse(e);this.emit("success",i),this.stateMachine.transition("authenticated"),this.transport?.send({type:"confirm",sessionID:this.sessionId});}catch{this.fail(new Error("Failed to decrypt authentication data")),this.restartIfContinuous();}}async startDeepLinkFlow(){let n=await this.fetchRelayUrl(false);this.sessionKey&&Jn(this.sessionId,this.sessionKey,10*6e4),await this.emitDeepLink(n),this.stateMachine.transition("awaiting-pair");}clearBackupCheck(){this.backupCheckTimeout&&(clearTimeout(this.backupCheckTimeout),this.backupCheckTimeout=void 0);}async checkSession(){let n=Zn();if(!n)return this.fail(new Error("Session not found"));this.stateMachine.transition("awaiting-auth");try{let e=await fetch(`${Sr}/session?session_id=${n.sessionId}`);if(!e.ok)return this.fail(new Error("Session not found"));let i=await e.json(),a=this.crypto.decryptSymmetric({encrypted:{cipher:i.cipher,nonce:i.nonce},keyString:n.sessionKey});if(!a)return console.warn("Failed to decrypt session"),this.fail(new Error("Failed to decrypt session"));let l=JSON.parse(a);this.clearBackupCheck(),je(),this.emit("success",l),this.stateMachine.transition("authenticated"),this.config.continuousMode?setTimeout(()=>{this.stateMachine.transition("idle"),this.start();},1500):this.stateMachine.transition("idle");}catch(e){return console.debug("Session check failed:",e),this.fail(new Error("Session check failed"))}}async emitQRCode(){let n={sessionID:this.sessionId,sessionKey:this.sessionKey,publicKey:this.config.publicKey,authType:this.config.authType,projectId:this.config.projectId,url:window.location.href},e=await hf.default.toDataURL(JSON.stringify(n),{type:"image/png",scale:3,color:{light:"#ffffff",dark:"#424242ff"}});this.emit("qr",e);}async emitDeepLink(n){let e=`${n}?sessionID=${encodeURIComponent(this.sessionId)}&sessionKey=${encodeURIComponent(this.sessionKey)}&publicKey=${encodeURIComponent(this.config.publicKey)}&authType=${this.config.authType}&projectId=${encodeURIComponent(this.config.projectId)}&url=${encodeURIComponent(n)}`;this.emit("deeplink",e);}attachVisibilityRecovery(){this.visibilityHandler=async()=>{document.visibilityState==="visible"&&(this.useWebSocket||await this.checkSession());},document.addEventListener("visibilitychange",this.visibilityHandler);}detachVisibilityRecovery(){this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=void 0);}async fetchRelayUrl(n){let{publicKey:e,projectId:i,authType:a}=this.config,l=await fetch(`${Sr}/relay?public_key=${e}&auth_type=${a}&project_id=${i}`);if(!l.ok){let p=await l.text();throw new Error(p)}let u=await l.json();return n?u.relay_url:u.deeplink_url}terminate(n){this.clearBackupCheck(),this.transport&&(n||this.transport.send({type:"client-terminated",sessionID:this.sessionId,projectId:this.config.projectId,publicKey:this.config.publicKey,authType:this.config.authType}),this.transport.close(),this.transport=void 0),je(),this.resetSession(),this.config.continuousMode||this.detachVisibilityRecovery(),this.stateMachine.transition(n?"confirmed":"idle");}restartIfContinuous(){this.stateMachine.transition("idle"),this.clearBackupCheck(),this.transport?.close(),this.transport=void 0,this.config.continuousMode&&setTimeout(()=>{this.start();},150);}resetSession(){this.sessionId="",this.sessionKey=null;}emit(n,e){this.listeners[n]?.forEach(i=>i(e));}fail(n){this.emit("error",n),this.stateMachine.transition("error");}};Mt.BASEURL=Sr;Mt.CryptoService=Wn;Mt.PelicanAuthentication=pf;Mt.StateMachine=Qn;Mt.Transport=Gn;Mt.clearAllAuthData=gf;Mt.clearAuthSession=je;Mt.getAuthSession=Zn;Mt.storeAuthSession=Jn;});var ti=gi(Xn());function yf(){if(document.getElementById("pelican-auth-styles"))return;let n=document.createElement("style");n.id="pelican-auth-styles",n.textContent=`@keyframes fadeUp {
9
9
  from {
10
10
  opacity: 0;
11
11
  transform: translateY(20px);