@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.mjs CHANGED
@@ -5,7 +5,7 @@ Make sure your charset is UTF-8`);i=(i>>>8&255)*192+(i&255),n.put(i,13);}};_n.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=Xi(e,i,l),y=Ne.getSymbolSize(e),E=new Yi(y);return Wi(E,e),Ji(E),Zi(E,e),br(E,i,0),e>=7&&Qi(E,e),Gi(E,p),isNaN(a)&&(a=wr.getBestMask(E,br.bind(null,E,i))),wr.applyMask(a,E),br(E,i,a),{modules:E,version:e,errorCorrectionLevel:i,maskPattern:a,segments:l}}zn.create=function(e,i){if(typeof e>"u"||e==="")throw new Error("No input text");let a=pr.M,l,u;return typeof i<"u"&&(a=pr.from(i.errorCorrectionLevel,pr.M),l=Pe.from(i.version),u=wr.from(i.maskPattern),i.toSJISFunc&&Ne.setToSJISFunction(i.toSJISFunc)),ef(e,l,a,u)};});var vr=rt(Kt=>{function Dn(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:Dn(e.color.dark||"#000000ff"),light:Dn(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 On=rt(ke=>{var Cr=vr();function rf(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 nf(){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=nf()),l=Cr.getOptions(l);let p=Cr.getImageWidth(e.modules.size,l),y=u.getContext("2d"),E=y.createImageData(p,p);return Cr.qrToImageData(E.data,e,l),rf(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 Fn=rt(Yn=>{var ff=vr();function qn(n,e){let i=n.a/255,a=e+'="'+n.hex+'"';return i<1?a+" "+e+'-opacity="'+i.toFixed(2).slice(1)+'"':a}function Er(n,e,i){let a=n+e;return typeof i<"u"&&(a+=" "+i),a}function of(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?Er("M",E+i,.5+V+i):Er("m",l,0),l=0,u=false),E+1<e&&n[y+1]||(a+=Er("h",p),p=0)):l++;}return a}Yn.render=function(e,i,a){let l=ff.getOptions(i),u=e.modules.size,p=e.modules.data,y=u+l.margin*2,E=l.color.light.a?"<path "+qn(l.color.light,"fill")+' d="M0 0h'+y+"v"+y+'H0z"/>':"",V="<path "+qn(l.color.dark,"stroke")+' d="'+of(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 $n=rt(xe=>{var sf=Hr(),Ar=jn(),Kn=On(),af=Fn();function Sr(n,e,i,a,l){let u=[].slice.call(arguments,1),p=u.length,y=typeof u[p-1]=="function";if(!y&&!sf())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 $=Ar.create(i,a);E(n($,e,a));}catch($){V($);}})}try{let E=Ar.create(i,a);l(null,n(E,e,a));}catch(E){l(E);}}xe.create=Ar.create;xe.toCanvas=Sr.bind(null,Kn.render);xe.toDataURL=Sr.bind(null,Kn.renderToDataURL);xe.toString=Sr.bind(null,function(n,e,i){return af.render(n,i)});});var Gn=rt(Mt=>{var cf=Yr(),$t=Kr(),lf=$n();function Hn(n){return n&&n.__esModule?n:{default:n}}var ze=Hn(cf),uf=Hn(lf),Vn=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}}},hf=Vn,df=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 df,Wn=(n,e,i)=>{De.set("session",{sessionId:n,sessionKey:e},{ttlMs:i});},Jn=()=>De.get("session"),je=()=>{De.remove("session");},xf=()=>{De.clear();},Zn=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)}},Qn=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}},_r="https://identityapi.pelicanidentity.com",gf=class{constructor(n){if(this.crypto=new hf,this.stateMachine=new Zn,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 Qn({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&&Wn(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=Jn();if(n){this.stateMachine.transition("awaiting-auth");try{let e=await fetch(`${_r}/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 uf.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(`${_r}/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=_r;Mt.CryptoService=Vn;Mt.PelicanAuthentication=gf;Mt.StateMachine=Zn;Mt.Transport=Qn;Mt.clearAllAuthData=xf;Mt.clearAuthSession=je;Mt.getAuthSession=Jn;Mt.storeAuthSession=Wn;});var Xn=xi(Gn());function pf(){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 $n=rt(xe=>{var sf=Hr(),Ar=jn(),Kn=On(),af=Fn();function Sr(n,e,i,a,l){let u=[].slice.call(arguments,1),p=u.length,y=typeof u[p-1]=="function";if(!y&&!sf())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 $=Ar.create(i,a);E(n($,e,a));}catch($){V($);}})}try{let E=Ar.create(i,a);l(null,n(E,e,a));}catch(E){l(E);}}xe.create=Ar.create;xe.toCanvas=Sr.bind(null,Kn.render);xe.toDataURL=Sr.bind(null,Kn.renderToDataURL);xe.toString=Sr.bind(null,function(n,e,i){return af.render(n,i)});});var Gn=rt(Mt=>{var cf=Yr(),$t=Kr(),lf=$n();function Hn(n){return n&&n.__esModule?n:{default:n}}var ze=Hn(cf),uf=Hn(lf),Vn=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}}},hf=Vn,df=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 df,Wn=(n,e,i)=>{De.set("session",{sessionId:n,sessionKey:e},{ttlMs:i});},Jn=()=>De.get("session"),je=()=>{De.remove("session");},xf=()=>{De.clear();},Zn=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)}},Qn=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}},_r="https://identityapi.pelicanidentity.com",gf=class{constructor(n){if(this.crypto=new hf,this.stateMachine=new Zn,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 Qn({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&&Wn(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=Jn();if(!n)return this.fail(new Error("Session not found"));this.stateMachine.transition("awaiting-auth");try{let e=await fetch(`${_r}/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 uf.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(`${_r}/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=_r;Mt.CryptoService=Vn;Mt.PelicanAuthentication=gf;Mt.StateMachine=Zn;Mt.Transport=Qn;Mt.clearAllAuthData=xf;Mt.clearAuthSession=je;Mt.getAuthSession=Jn;Mt.storeAuthSession=Wn;});var Xn=xi(Gn());function pf(){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);