@trymellon/js 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/angular.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- "use strict";var mr=Object.create;var N=Object.defineProperty;var Ue=Object.getOwnPropertyDescriptor;var gr=Object.getOwnPropertyNames;var fr=Object.prototype.hasOwnProperty;var Fe=(e,r)=>(r=Symbol[e])?r:Symbol.for("Symbol."+e),V=e=>{throw TypeError(e)};var Rr=(e,r,t)=>r in e?N(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var De=(e,r)=>N(e,"name",{value:r,configurable:!0});var yr=(e,r)=>{for(var t in r)N(e,t,{get:r[t],enumerable:!0})},vr=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of gr(r))!fr.call(e,s)&&s!==t&&N(e,s,{get:()=>r[s],enumerable:!(n=Ue(r,s))||n.enumerable});return e};var hr=e=>vr(N({},"__esModule",{value:!0}),e);var Le=e=>[,,,mr(e?.[Fe("metadata")]??null)],Ke=["class","method","getter","setter","accessor","field","value","get","set"],q=e=>e!==void 0&&typeof e!="function"?V("Function expected"):e,Er=(e,r,t,n,s)=>({kind:Ke[e],name:r,metadata:n,addInitializer:i=>t._?V("Already initialized"):s.push(q(i||null))}),br=(e,r)=>Rr(r,Fe("metadata"),e[3]),je=(e,r,t,n)=>{for(var s=0,i=e[r>>1],a=i&&i.length;s<a;s++)r&1?i[s].call(t):n=i[s].call(t,n);return n},qe=(e,r,t,n,s,i)=>{var a,l,m,v,R,g=r&7,h=!!(r&8),b=!!(r&16),I=g>3?e.length+1:g?h?1:2:0,O=Ke[g+5],j=g>3&&(e[I-1]=[]),C=e[I]||(e[I]=[]),T=g&&(!b&&!h&&(s=s.prototype),g<5&&(g>3||!b)&&Ue(g<4?s:{get[t](){return we(this,i)},set[t](A){return Ne(this,i,A)}},t));g?b&&g<4&&De(i,(g>2?"set ":g>1?"get ":"")+t):De(s,t);for(var ae=n.length-1;ae>=0;ae--)v=Er(g,t,m={},e[3],C),g&&(v.static=h,v.private=b,R=v.access={has:b?A=>_r(s,A):A=>t in A},g^3&&(R.get=b?A=>(g^1?we:Tr)(A,s,g^4?i:T.get):A=>A[t]),g>2&&(R.set=b?(A,le)=>Ne(A,s,le,g^4?i:T.set):(A,le)=>A[t]=le)),l=(0,n[ae])(g?g<4?b?i:T[O]:g>4?void 0:{get:T.get,set:T.set}:s,v),m._=1,g^4||l===void 0?q(l)&&(g>4?j.unshift(l):g?b?i=l:T[O]=l:s=l):typeof l!="object"||l===null?V("Object expected"):(q(a=l.get)&&(T.get=a),q(a=l.set)&&(T.set=a),q(a=l.init)&&j.unshift(a));return g||br(e,s),T&&N(s,t,T),b?g^4?i:T:s};var ue=(e,r,t)=>r.has(e)||V("Cannot "+t),_r=(e,r)=>Object(r)!==r?V('Cannot use the "in" operator on this value'):e.has(r),we=(e,r,t)=>(ue(e,r,"read from private field"),t?t.call(e):r.get(e));var Ne=(e,r,t,n)=>(ue(e,r,"write to private field"),n?n.call(e,t):r.set(e,t),t),Tr=(e,r,t)=>(ue(e,r,"access private method"),t);var Br={};yr(Br,{TRYMELLON_CONFIG:()=>H,TryMellonService:()=>w,provideTryMellonConfig:()=>Wr});module.exports=hr(Br);var K=require("@angular/core");var d=e=>({ok:!0,value:e}),c=e=>({ok:!1,error:e});var G=class e extends Error{code;details;isTryMellonError=!0;constructor(r,t,n){super(t),this.name="TryMellonError",this.code=r,this.details=n,Error.captureStackTrace&&Error.captureStackTrace(this,e)}},Ar={NOT_SUPPORTED:"WebAuthn is not supported in this environment",USER_CANCELLED:"User cancelled the operation",PASSKEY_NOT_FOUND:"Passkey not found",SESSION_EXPIRED:"Session has expired",NETWORK_FAILURE:"Network request failed",INVALID_ARGUMENT:"Invalid argument provided",TIMEOUT:"Operation timed out",ABORTED:"Operation was aborted",ABORT_ERROR:"Operation aborted by user or timeout",CHALLENGE_MISMATCH:"This link was already used or expired. Please try again from your computer.",UNKNOWN_ERROR:"An unknown error occurred"};function y(e,r,t){return new G(e,r??Ar[e],t)}function ce(e){return e instanceof G||typeof e=="object"&&e!==null&&"isTryMellonError"in e&&e.isTryMellonError===!0}function Ve(){return y("NOT_SUPPORTED")}function E(e,r){return y("INVALID_ARGUMENT",`Invalid argument: ${e} - ${r}`,{field:e,reason:r})}function We(e){return y("UNKNOWN_ERROR",`Failed to ${e} credential`,{operation:e})}function pe(e){return y("NOT_SUPPORTED",`No base64 ${e==="encode"?"encoding":"decoding"} available`,{type:e})}function de(e,r){try{let t=new URL(e);if(t.protocol!=="https:"&&t.protocol!=="http:")throw E(r,"must use http or https protocol")}catch(t){throw ce(t)?t:E(r,"must be a valid URL")}}function P(e,r,t,n){if(!Number.isFinite(e))throw E(r,"must be a finite number");if(e<t||e>n)throw E(r,`must be between ${t} and ${n}`)}function X(e,r){if(typeof e!="string"||e.length===0)throw E(r,"must be a non-empty string");if(!/^[A-Za-z0-9_-]+$/.test(e))throw E(r,"must be a valid base64url string")}var Ir={NotAllowedError:"USER_CANCELLED",AbortError:"ABORTED",NotSupportedError:"NOT_SUPPORTED",SecurityError:"NOT_SUPPORTED",InvalidStateError:"UNKNOWN_ERROR",UnknownError:"UNKNOWN_ERROR"};function W(e){if(typeof e!="string")return"UNKNOWN_ERROR";let r=e.toLowerCase().trim();return{challenge_mismatch:"CHALLENGE_MISMATCH",session_expired:"SESSION_EXPIRED",unauthorized:"SESSION_EXPIRED",validation_error:"INVALID_ARGUMENT",invalid_argument:"INVALID_ARGUMENT",user_not_found:"SESSION_EXPIRED",passkey_not_found:"PASSKEY_NOT_FOUND"}[r]??"UNKNOWN_ERROR"}function _(e){if(e instanceof DOMException){let r=e.name,t=e.message||"WebAuthn operation failed",n=Ir[r]??"UNKNOWN_ERROR";return y(n,t,{originalError:e})}return e instanceof Error?y("UNKNOWN_ERROR",e.message,{originalError:e}):y("UNKNOWN_ERROR","An unknown error occurred",{originalError:e})}function f(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function u(e){return typeof e=="string"}function S(e){return typeof e=="number"&&Number.isFinite(e)}function Y(e){return typeof e=="boolean"}function U(e){return Array.isArray(e)}function o(e,r){return c(y("UNKNOWN_ERROR",e,{...r,originalData:r?.originalData}))}function p(e,r){return e[r]}function Be(e,r){return!f(e)||!u(e.name)||!u(e.id)?o("Invalid API response: challenge.rp must have name and id strings",{originalData:r}):d(!0)}function He(e,r){return!f(e)||!u(e.id)||!u(e.name)||!u(e.displayName)?o("Invalid API response: challenge.user must have id, name, displayName strings",{originalData:r}):d(!0)}function Ge(e,r){if(!U(e))return o("Invalid API response: challenge.pubKeyCredParams must be array",{originalData:r});for(let t of e)if(!f(t)||t.type!=="public-key"||!S(t.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:r});return d(!0)}function me(e,r){if(!f(e))return o("Invalid API response: user must be object",{field:"user",originalData:r});let t=p(e,"user_id"),n=p(e,"external_user_id");if(!u(t)||!u(n))return o("Invalid API response: user must have user_id and external_user_id strings",{originalData:r});let s=e.email,i=e.metadata;return s!==void 0&&!u(s)?o("Invalid API response: user.email must be string",{originalData:r}):i!==void 0&&(typeof i!="object"||i===null)?o("Invalid API response: user.metadata must be object",{originalData:r}):d({user_id:t,external_user_id:n,...s!==void 0&&{email:s},...i!==void 0&&{metadata:i}})}function ge(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"session_id");if(!u(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});let t=p(e,"challenge");if(!f(t))return o("Invalid API response: challenge must be object",{field:"challenge",originalData:e});let n=Be(p(t,"rp"),e);if(!n.ok)return n;let s=He(p(t,"user"),e);if(!s.ok)return s;let i=p(t,"challenge");if(!u(i))return o("Invalid API response: challenge.challenge must be string",{originalData:e});let a=Ge(p(t,"pubKeyCredParams"),e);if(!a.ok)return a;let l=t.timeout;if(l!==void 0&&!S(l))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let m=t.excludeCredentials;if(m!==void 0){if(!U(m))return o("Invalid API response: excludeCredentials must be array",{originalData:e});for(let R of m)if(!f(R)||R.type!=="public-key"||!u(R.id))return o("Invalid API response: excludeCredentials items must have id and type",{originalData:e})}let v=t.authenticatorSelection;return v!==void 0&&!f(v)?o("Invalid API response: authenticatorSelection must be object",{originalData:e}):d({session_id:r,challenge:{rp:t.rp,user:t.user,challenge:i,pubKeyCredParams:t.pubKeyCredParams,...l!==void 0&&{timeout:l},...m!==void 0&&{excludeCredentials:m},...v!==void 0&&{authenticatorSelection:v}}})}function fe(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"session_id");if(!u(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});let t=p(e,"challenge");if(!f(t))return o("Invalid API response: challenge must be object",{field:"challenge",originalData:e});let n=p(t,"challenge"),s=p(t,"rpId"),i=t.allowCredentials;if(!u(n))return o("Invalid API response: challenge.challenge must be string",{originalData:e});if(!u(s))return o("Invalid API response: challenge.rpId must be string",{originalData:e});if(i!==void 0&&!U(i))return o("Invalid API response: allowCredentials must be array",{originalData:e});if(i){for(let m of i)if(!f(m)||m.type!=="public-key"||!u(m.id))return o("Invalid API response: allowCredentials items must have id and type",{originalData:e})}let a=t.timeout;if(a!==void 0&&!S(a))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let l=t.userVerification;return l!==void 0&&!["required","preferred","discouraged"].includes(String(l))?o("Invalid API response: userVerification must be required|preferred|discouraged",{originalData:e}):d({session_id:r,challenge:{challenge:n,rpId:s,allowCredentials:i??[],...a!==void 0&&{timeout:a},...l!==void 0&&{userVerification:l}}})}function Re(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"credential_id"),t=p(e,"status"),n=p(e,"session_token"),s=p(e,"user");if(!u(r))return o("Invalid API response: credential_id must be string",{field:"credential_id",originalData:e});if(!u(t))return o("Invalid API response: status must be string",{field:"status",originalData:e});if(!u(n))return o("Invalid API response: session_token must be string",{field:"session_token",originalData:e});let i=me(s,e);if(!i.ok)return o(i.error.message,{originalData:e});let a=e.redirect_url;return a!==void 0&&!u(a)?o("Invalid API response: redirect_url must be string",{originalData:e}):d({credential_id:r,status:t,session_token:n,user:i.value,...a!==void 0&&{redirect_url:a}})}function ye(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"authenticated"),t=p(e,"session_token"),n=p(e,"user"),s=p(e,"signals");if(!Y(r))return o("Invalid API response: authenticated must be boolean",{field:"authenticated",originalData:e});if(!u(t))return o("Invalid API response: session_token must be string",{field:"session_token",originalData:e});let i=me(n,e);if(!i.ok)return o(i.error.message,{originalData:e});if(s!==void 0&&!f(s))return o("Invalid API response: signals must be object",{originalData:e});let a=e.redirect_url;return a!==void 0&&!u(a)?o("Invalid API response: redirect_url must be string",{originalData:e}):d({authenticated:r,session_token:t,user:i.value,signals:s,...a!==void 0&&{redirect_url:a}})}function ve(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"valid"),t=p(e,"user_id"),n=p(e,"external_user_id"),s=p(e,"tenant_id"),i=p(e,"app_id");return Y(r)?u(t)?u(n)?u(s)?u(i)?d({valid:r,user_id:t,external_user_id:n,tenant_id:s,app_id:i}):o("Invalid API response: app_id must be string",{field:"app_id",originalData:e}):o("Invalid API response: tenant_id must be string",{field:"tenant_id",originalData:e}):o("Invalid API response: external_user_id must be string",{field:"external_user_id",originalData:e}):o("Invalid API response: user_id must be string",{field:"user_id",originalData:e}):o("Invalid API response: valid must be boolean",{field:"valid",originalData:e})}function he(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=e.session_token??e.sessionToken;if(!u(r))return o("Invalid API response: session_token/sessionToken must be string",{field:"session_token",originalData:e});let t=e.redirect_url;return t!==void 0&&!u(t)?o("Invalid API response: redirect_url must be string",{originalData:e}):d({sessionToken:r,...t!==void 0&&{redirectUrl:t}})}var Cr=["pending_passkey","pending_data","completed"],Or=["pending_data","completed"];function Ee(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"session_id"),t=p(e,"onboarding_url"),n=p(e,"expires_in");return u(r)?u(t)?S(n)?d({session_id:r,onboarding_url:t,expires_in:n}):o("Invalid API response: expires_in must be number",{field:"expires_in",originalData:e}):o("Invalid API response: onboarding_url must be string",{field:"onboarding_url",originalData:e}):o("Invalid API response: session_id must be string",{field:"session_id",originalData:e})}function be(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"status"),t=p(e,"onboarding_url"),n=p(e,"expires_in");return!u(r)||!Cr.includes(r)?o("Invalid API response: status must be pending_passkey|pending_data|completed",{field:"status",originalData:e}):u(t)?S(n)?d({status:r,onboarding_url:t,expires_in:n}):o("Invalid API response: expires_in must be number",{originalData:e}):o("Invalid API response: onboarding_url must be string",{originalData:e})}function _e(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"session_id"),t=p(e,"status"),n=p(e,"onboarding_url");if(!u(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});if(t!=="pending_passkey")return o("Invalid API response: status must be pending_passkey",{field:"status",originalData:e});if(!u(n))return o("Invalid API response: onboarding_url must be string",{originalData:e});let s=e.challenge,i;if(s!==void 0){let a=kr(s);if(!a.ok)return a;i=a.value}return d({session_id:r,status:"pending_passkey",onboarding_url:n,...i!==void 0&&{challenge:i}})}function kr(e){if(!f(e))return o("Invalid API response: challenge must be object",{originalData:e});let r=p(e,"rp"),t=p(e,"user"),n=p(e,"challenge"),s=p(e,"pubKeyCredParams");if(!f(r)||!u(r.name)||!u(r.id))return o("Invalid API response: challenge.rp must have name and id",{originalData:e});if(!f(t)||!u(t.id)||!u(t.name)||!u(t.displayName))return o("Invalid API response: challenge.user must have id, name, displayName",{originalData:e});if(!u(n))return o("Invalid API response: challenge.challenge must be string",{originalData:e});if(!U(s))return o("Invalid API response: challenge.pubKeyCredParams must be array",{originalData:e});for(let i of s)if(!f(i)||i.type!=="public-key"||!S(i.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});return d({rp:r,user:t,challenge:n,pubKeyCredParams:s})}function Te(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"session_id"),t=p(e,"status"),n=p(e,"user_id"),s=p(e,"tenant_id");return u(r)?!u(t)||!Or.includes(t)?o("Invalid API response: status must be pending_data|completed",{originalData:e}):u(n)?u(s)?d({session_id:r,status:t,user_id:n,tenant_id:s}):o("Invalid API response: tenant_id must be string",{originalData:e}):o("Invalid API response: user_id must be string",{originalData:e}):o("Invalid API response: session_id must be string",{originalData:e})}function Ae(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"session_id"),t=p(e,"status"),n=p(e,"user_id"),s=p(e,"tenant_id"),i=p(e,"session_token");return u(r)?t!=="completed"?o("Invalid API response: status must be completed",{originalData:e}):!u(n)||!u(s)||!u(i)?o("Invalid API response: user_id, tenant_id, session_token must be strings",{originalData:e}):d({session_id:r,status:"completed",user_id:n,tenant_id:s,session_token:i}):o("Invalid API response: session_id must be string",{originalData:e})}function z(e){return e==null?d(void 0):f(e)&&Object.keys(e).length===0?d(void 0):o("Invalid API response: expected empty body (204)",{originalData:e})}function Sr(e){if(!e||typeof e!="object")return!1;let r=e;return typeof r.challenge=="string"&&r.rp!=null&&typeof r.rp=="object"&&r.user!=null&&typeof r.user=="object"&&Array.isArray(r.pubKeyCredParams)}function xr(e){if(!e||typeof e!="object")return!1;let r=e;return typeof r.challenge=="string"&&typeof r.rpId=="string"}function $(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r="resultado"in e&&f(e.resultado)?e.resultado:e,t=r.session_id,n=r.qr_url,s=r.expires_at,i=r.polling_token;if(!u(t)||!u(n)||!u(s)||!u(i))return o("Invalid API response: missing required fields",{originalData:e});let a={session_id:t,qr_url:n,expires_at:s,polling_token:i};return r.external_user_id!==void 0&&u(r.external_user_id)&&(a.external_user_id=r.external_user_id),d(a)}function Ie(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r="resultado"in e&&f(e.resultado)?e.resultado:e,t=r.status;if(!u(t)||!["pending","authenticated","completed"].includes(t))return o("Invalid API response: invalid status",{originalData:e});let n=r.user_id,s=r.session_token,i=r.redirect_url;return n!==void 0&&!u(n)?o("Invalid API response: user_id must be a string when present",{originalData:e}):s!==void 0&&!u(s)?o("Invalid API response: session_token must be a string when present",{originalData:e}):i!==void 0&&!u(i)?o("Invalid API response: redirect_url must be a string when present",{originalData:e}):d({status:t,user_id:n,session_token:s,redirect_url:i})}function Ce(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=e.type,t=r==="registration"?"registration":"auth",n=e.options;if(!f(n))return o("Invalid API response: options are required",{originalData:e});let s=200,i=Xe(e.approval_context,s),a=Xe(e.application_name,s);if(i===!1||a===!1)return o("Invalid API response: approval_context/application_name must be string max 200 chars",{originalData:e});let l={};return typeof i=="string"&&(l.approval_context=i),typeof a=="string"&&(l.application_name=a),t==="registration"?Sr(n)?d({type:"registration",options:n,...l}):o("Invalid API response: registration options must have challenge, rp, user, pubKeyCredParams",{originalData:e}):xr(n)?d({type:"auth",options:n,...l}):o("Invalid API response: auth options must have challenge and rpId",{originalData:e})}function Xe(e,r){if(e!=null)return typeof e!="string"||e.length>r?!1:e}function Oe(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"challenge"),t=p(e,"recovery_session_id");return f(r)?u(t)?d({challenge:r,recovery_session_id:t}):o("Invalid API response: recovery_session_id must be string",{field:"recovery_session_id",originalData:e}):o("Invalid API response: challenge must be object",{field:"challenge",originalData:e})}function ke(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"status"),t=p(e,"session_token"),n=p(e,"user"),s=p(e,"credential_id");if(!u(r))return o("Invalid API response: status must be string",{field:"status",originalData:e});if(!u(t))return o("Invalid API response: session_token must be string",{field:"session_token",originalData:e});if(!u(s))return o("Invalid API response: credential_id must be string",{field:"credential_id",originalData:e});if(!f(n))return o("Invalid API response: user must be object",{field:"user",originalData:e});let i=p(n,"user_id");if(!u(i))return o("Invalid API response: user.user_id must be string",{field:"user.user_id",originalData:e});let l=e.redirect_url;if(l!==void 0&&!u(l))return o("Invalid API response: redirect_url must be string",{field:"redirect_url",originalData:e});let m=n;return d({status:r,session_token:t,credential_id:s,user:{user_id:i,external_user_id:u(m.external_user_id)?m.external_user_id:void 0,email:u(m.email)?m.email:void 0,metadata:f(m.metadata)?m.metadata:void 0},...l!==void 0&&{redirect_url:l}})}var J=class{constructor(r,t,n={}){this.httpClient=r;this.baseUrl=t;this.defaultHeaders=n}mergeHeaders(r){return{...this.defaultHeaders,...r}}async post(r,t,n){let s=`${this.baseUrl}${r}`,i=await this.httpClient.post(s,t,this.mergeHeaders());return i.ok?n(i.value):c(i.error)}async get(r,t,n){let s=`${this.baseUrl}${r}`,i=await this.httpClient.get(s,this.mergeHeaders(n));return i.ok?t(i.value):c(i.error)}async startRegister(r){return this.post("/v1/passkeys/register/start",r,ge)}async startAuth(r){return this.post("/v1/passkeys/auth/start",r,fe)}async finishRegister(r){return this.post("/v1/passkeys/register/finish",r,Re)}async finishAuthentication(r){return this.post("/v1/passkeys/auth/finish",r,ye)}async validateSession(r){return this.get("/v1/sessions/validate",ve,{Authorization:`Bearer ${r}`})}async startEmailFallback(r){let t=`${this.baseUrl}/v1/fallback/email/start`,n=await this.httpClient.post(t,{userId:r.userId,email:r.email},this.mergeHeaders());return n.ok?d(void 0):c(n.error)}async verifyEmailCode(r){let t={userId:r.userId,code:r.code};return r.successUrl&&(t.success_url=r.successUrl),this.post("/v1/fallback/email/verify",t,he)}async startOnboarding(r){return this.post("/v1/onboarding/start",r,Ee)}async getOnboardingStatus(r){return this.get(`/v1/onboarding/${r}/status`,be)}async getOnboardingRegister(r){return this.get(`/v1/onboarding/${r}/register`,_e)}async registerOnboardingPasskey(r,t){return this.post(`/v1/onboarding/${r}/register-passkey`,t,Te)}async completeOnboarding(r,t){return this.post(`/v1/onboarding/${r}/complete`,t,Ae)}async initCrossDeviceAuth(){return this.post("/v1/auth/cross-device/init",{},$)}async initCrossDeviceRegistration(r){let t=typeof r?.externalUserId=="string"?r.externalUserId.trim():"",n=t.length>0?{external_user_id:t}:{};return this.post("/v1/auth/cross-device/init-registration",n,$)}async getCrossDeviceStatus(r,t){let n={};return typeof t=="string"&&t.length>0&&(n["X-Polling-Token"]=t),this.get(`/v1/auth/cross-device/status/${r}`,Ie,Object.keys(n).length>0?n:void 0)}async getCrossDeviceContext(r){return this.get(`/v1/auth/cross-device/context/${r}`,Ce)}async verifyCrossDeviceAuth(r){return this.post("/v1/auth/cross-device/verify",r,z)}async verifyCrossDeviceRegistration(r){return this.post("/v1/auth/cross-device/verify-registration",r,z)}async verifyAccountRecoveryOtp(r,t){return this.post("/v1/users/recovery/verify",{external_id:r,otp:t},Oe)}async completeAccountRecovery(r,t){return this.post("/v1/users/recovery/complete",{recovery_session_id:r,credential:t},ke)}};function Pr(e){return typeof e=="object"&&e!==null&&e.ok===!0&&"resultado"in e}function $e(e){if(typeof e!="object"||e===null)return!1;let r=e;if(r.ok!==!1||!r.error||typeof r.error!="object")return!1;let t=r.error;return typeof t.code=="string"&&typeof t.message=="string"}function Ye(e,r){if($e(e))return{message:e.error.message,code:W(e.error.code)};let t=e,n=t?.error;if(typeof n=="object"&&n!==null&&"code"in n&&typeof n.code=="string")return{message:n.message??t?.message??r,code:W(n.code)};let s=t?.message??r,i=t?.error,a=typeof i=="string"?W(i):i===void 0?"NETWORK_FAILURE":W(String(i));return{message:s,code:a}}var Mr=3e4;function Dr(){if(typeof globalThis.crypto<"u"&&typeof globalThis.crypto.randomUUID=="function")return globalThis.crypto.randomUUID();throw new Error("Web Crypto API is required but not available.")}function ze(e,r){let t=r*Math.pow(2,e);return Math.min(t,Mr)}function wr(e,r){return e!=="GET"?!1:r>=500||r===429}var Z=class{constructor(r,t=0,n=1e3,s){this.timeoutMs=r;this.maxRetries=t;this.retryDelayMs=n;this.logger=s}async get(r,t){return this.request(r,{method:"GET",headers:t})}async post(r,t,n){return this.request(r,{method:"POST",body:JSON.stringify(t),headers:{"Content-Type":"application/json",...n}})}async request(r,t){let n=(t.method??"GET").toUpperCase(),s=Dr(),i=new Headers(t.headers);i.set("X-Request-Id",s),this.logger&&this.logger.debug("request",{requestId:s,url:r,method:n});let a;for(let l=0;l<=this.maxRetries;l++)try{let m=new AbortController,v=setTimeout(()=>m.abort(),this.timeoutMs);try{let R=await fetch(r,{...t,headers:i,signal:m.signal});if(!R.ok){let I;try{I=await R.json()}catch{}let{message:O,code:j}=Ye(I,R.statusText),C=y(j,O,{requestId:s,status:R.status,statusText:R.statusText,data:I});if(wr(n,R.status)&&l<this.maxRetries){a=C,clearTimeout(v),await new Promise(T=>setTimeout(T,ze(l,this.retryDelayMs)));continue}return c(C)}if(R.status===204)return d(void 0);if(R.headers.get("content-length")==="0")return d(void 0);let h=await R.json();if(Pr(h))return d(h.resultado);let b=h;if(typeof h=="object"&&h!==null&&b.ok===!0&&!("resultado"in b))return d(void 0);if($e(h)){let{message:I,code:O}=Ye(h,R.statusText);return c(y(O,I,{requestId:s,status:R.status,statusText:R.statusText,data:h}))}return d(h)}finally{clearTimeout(v)}}catch(m){if(a=m,n==="GET"&&l<this.maxRetries)await new Promise(R=>setTimeout(R,ze(l,this.retryDelayMs)));else break}return a instanceof Error&&a.name==="AbortError"?c(y("TIMEOUT","Request timed out",{requestId:s})):c(y("NETWORK_FAILURE",a instanceof Error?a.message:"Request failed",{requestId:s,cause:a}))}};function k(e){let r=new Uint8Array(e),t=Array.from(r,s=>String.fromCharCode(s)).join("");if(typeof globalThis.btoa>"u")throw pe("encode");return globalThis.btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function Nr(e){if(typeof globalThis.atob>"u")throw pe("decode");let r=e.replace(/-/g,"+").replace(/_/g,"/"),t=r.length%4,n=t===0?r:r+"=".repeat(4-t),s=globalThis.atob(n);return Uint8Array.from(s,i=>i.charCodeAt(0))}function F(e){let r=Nr(e),t=new ArrayBuffer(r.length);return new Uint8Array(t).set(r),t}function Je(e){return e!==null&&typeof e=="object"&&"clientDataJSON"in e&&e.clientDataJSON instanceof ArrayBuffer}function x(e){if(!e.response)throw y("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!Je(r))throw y("UNKNOWN_ERROR","Invalid credential response structure",{response:r});if(!("attestationObject"in r))throw y("UNKNOWN_ERROR","Invalid credential response structure for register: attestationObject is missing",{response:r});let t=r.clientDataJSON,n=r.attestationObject;return{id:e.id,rawId:k(e.rawId),response:{clientDataJSON:k(t),attestationObject:k(n)},type:"public-key"}}function Q(e){if(!e.response)throw y("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!Je(r))throw y("UNKNOWN_ERROR","Invalid credential response structure",{response:r});if(!("authenticatorData"in r)||!("signature"in r))throw y("UNKNOWN_ERROR","Invalid credential response structure for auth: authenticatorData or signature is missing",{response:r});let t=r.clientDataJSON,n=r.authenticatorData,s=r.signature,i=r.userHandle;return{id:e.id,rawId:k(e.rawId),response:{authenticatorData:k(n),clientDataJSON:k(t),signature:k(s),...i&&{userHandle:k(i)}},type:"public-key"}}function L(){try{return!(typeof navigator>"u"||!navigator.credentials||typeof PublicKeyCredential>"u")}catch{return!1}}async function Ur(){try{return!L()||typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable!="function"?!1:await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}async function Ze(){let e=L(),r=await Ur();return{isPasskeySupported:e,platformAuthenticatorAvailable:r,recommendedFlow:e?"passkey":"fallback"}}function M(e,r="create"){if(!e||typeof e!="object"||!("id"in e)||!("rawId"in e)||!("response"in e))throw We(r)}async function B(e){let{operation:r,eventEmitter:t,start:n,createOptions:s,invoke:i,finish:a}=e;try{if(t.emit("start",{type:"start",operation:r}),!L()){let g=Ve();return t.emit("error",{type:"error",error:g}),c(g)}let l=await n();if(!l.ok)return t.emit("error",{type:"error",error:l.error}),c(l.error);let m=s(l.value);if(!m.ok)return t.emit("error",{type:"error",error:m.error}),c(m.error);let v=await i(m.value);if(!v){let g=E("credential",`${r==="register"?"creation":"retrieval"} failed`);return t.emit("error",{type:"error",error:g}),c(g)}try{M(v)}catch(g){let h=_(g);return t.emit("error",{type:"error",error:h}),c(h)}let R=await a(l.value,v);return R.ok?d(R.value):(t.emit("error",{type:"error",error:R.error}),c(R.error))}catch(l){let m=_(l);return t.emit("error",{type:"error",error:m}),c(m)}}function D(e,r){try{X(e.challenge,"challenge"),X(e.user.id,"user.id");let t=F(e.challenge),n=F(e.user.id),s={userVerification:"preferred"};e.authenticatorSelection&&(s={...e.authenticatorSelection}),r&&(s={...s,authenticatorAttachment:r});let i={rp:{id:e.rp.id,name:e.rp.name},user:{id:n,name:e.user.name,displayName:e.user.displayName},challenge:t,pubKeyCredParams:e.pubKeyCredParams,...e.timeout!==void 0&&{timeout:e.timeout},attestation:"none",authenticatorSelection:s,...e.excludeCredentials&&{excludeCredentials:e.excludeCredentials.map(a=>({id:F(a.id),type:a.type,...a.transports&&{transports:a.transports}}))}};return d({publicKey:i})}catch(t){return c(_(t))}}function Se(e,r){try{X(e.challenge,"challenge");let t=F(e.challenge);return d({publicKey:{challenge:t,rpId:e.rpId,...e.timeout!==void 0&&{timeout:e.timeout},userVerification:e.userVerification??"preferred",...e.allowCredentials&&{allowCredentials:e.allowCredentials.map(n=>({id:F(n.id),type:n.type,...n.transports&&{transports:n.transports}}))}},...r!==void 0&&{mediation:r}})}catch(t){return c(_(t))}}async function Qe(e,r,t){let n=e.externalUserId??e.external_user_id;if(!n||typeof n!="string"||n.trim()===""){let i=E("externalUserId","must be a non-empty string");return t.emit("error",{type:"error",error:i}),c(i)}let s=await B({operation:"register",eventEmitter:t,start:()=>r.startRegister({external_user_id:n}),createOptions:i=>D(i.challenge,e.authenticatorType),invoke:async i=>{let a={...i,...e.signal&&{signal:e.signal}};return navigator.credentials.create(a)},finish:async(i,a)=>{let l=await r.finishRegister({session_id:i.session_id,credential:x(a),...e.successUrl&&{success_url:e.successUrl}});return l.ok?d({success:!0,credentialId:l.value.credential_id,credential_id:l.value.credential_id,status:l.value.status,sessionToken:l.value.session_token,user:{userId:l.value.user.user_id,externalUserId:l.value.user.external_user_id,email:l.value.user.email,metadata:l.value.user.metadata},...l.value.redirect_url&&{redirectUrl:l.value.redirect_url}}):c(l.error)}});return s.ok&&t.emit("success",{type:"success",operation:"register",token:s.value.sessionToken,user:s.value.user}),s}async function er(e,r,t){let n=e.externalUserId??e.external_user_id,s=n!==void 0&&typeof n=="string"&&n.trim()!=="",i=await B({operation:"authenticate",eventEmitter:t,start:()=>r.startAuth(s?{external_user_id:n.trim()}:{}),createOptions:a=>Se(a.challenge,e.mediation),invoke:async a=>{let l={...a,...e.signal&&{signal:e.signal}};return navigator.credentials.get(l)},finish:async(a,l)=>{let m=await r.finishAuthentication({session_id:a.session_id,credential:Q(l),...e.successUrl&&{success_url:e.successUrl}});return m.ok?d({authenticated:m.value.authenticated,sessionToken:m.value.session_token,user:{userId:m.value.user.user_id,externalUserId:m.value.user.external_user_id,email:m.value.user.email,metadata:m.value.user.metadata},signals:m.value.signals,...m.value.redirect_url&&{redirectUrl:m.value.redirect_url}}):c(m.error)}});return i.ok&&t.emit("success",{type:"success",operation:"authenticate",token:i.value.sessionToken,user:i.value.user}),i}async function ee(e,r){return r?r.aborted?"aborted":new Promise(t=>{let n=()=>{s(),t("aborted")},s=()=>{clearTimeout(i),r.removeEventListener("abort",n)},i=setTimeout(()=>{s(),t("completed")},e);r.addEventListener("abort",n)}):(await new Promise(t=>setTimeout(t,e)),"completed")}var Fr=2e3,Lr=60,re=class{constructor(r){this.apiClient=r}async startFlow(r,t){let n=await this.apiClient.startOnboarding({user_role:r.user_role});if(!n.ok)return c(n.error);let{session_id:s}=n.value;for(let i=0;i<Lr;i++){if(t?.aborted)return c(y("ABORT_ERROR","Operation aborted by user or timeout"));if(await ee(Fr,t)==="aborted")return c(y("ABORT_ERROR","Operation aborted by user or timeout"));let l=await this.apiClient.getOnboardingStatus(s);if(!l.ok)return c(l.error);let m=l.value.status,v=l.value.onboarding_url;if(m==="pending_passkey"){let R=await this.apiClient.getOnboardingRegister(s);if(!R.ok)return c(R.error);let g=R.value;if(!g.challenge)return c(y("NOT_SUPPORTED","Onboarding requires user action - complete passkey registration at the provided onboarding_url",{onboarding_url:v}));let h=D(g.challenge);if(!h.ok)return c(h.error);let b;try{b=await navigator.credentials.create(h.value)}catch(C){return c(_(C))}try{M(b,"create")}catch(C){return c(_(C))}let I;try{I=x(b)}catch(C){return c(_(C))}let O=await this.apiClient.registerOnboardingPasskey(s,{credential:I,challenge:g.challenge.challenge});return O.ok?await this.apiClient.completeOnboarding(s,{company_name:r.company_name}):c(O.error)}if(m==="completed")return await this.apiClient.completeOnboarding(s,{company_name:r.company_name})}return c(y("TIMEOUT","Onboarding timed out"))}};var Kr=2e3,jr=60,te=class{constructor(r){this.apiClient=r}async init(){return this.apiClient.initCrossDeviceAuth()}async initRegistration(r){return this.apiClient.initCrossDeviceRegistration(r)}async waitForSession(r,t,n){if(t?.aborted)return c(y("ABORT_ERROR","Operation aborted by user or timeout"));for(let s=0;s<jr;s++){let i=await this.apiClient.getCrossDeviceStatus(r,n);if(!i.ok)return c(i.error);if(i.value.status==="completed"){if(!i.value.session_token||!i.value.user_id)return c(y("UNKNOWN_ERROR","Missing data in completed session"));let l=i.value.redirect_url!=null&&i.value.redirect_url!==""?i.value.redirect_url:void 0;return d({session_token:i.value.session_token,user_id:i.value.user_id,...l!==void 0&&{redirectUrl:l}})}if(await ee(Kr,t)==="aborted")return c(y("ABORT_ERROR","Operation aborted by user or timeout"))}return c(y("TIMEOUT","Cross-device authentication timed out"))}async approve(r){let t=await this.apiClient.getCrossDeviceContext(r);if(!t.ok)return c(t.error);let n=t.value;return n.type==="registration"?this.executeRegistrationApproval(r,n):this.executeAuthApproval(r,n)}async executeRegistrationApproval(r,t){let n=D(t.options);if(!n.ok)return c(n.error);let s;try{s=await navigator.credentials.create(n.value)}catch(a){return c(_(a))}try{M(s,"create")}catch(a){return c(_(a))}let i;try{i=x(s)}catch(a){return c(_(a))}return this.apiClient.verifyCrossDeviceRegistration({session_id:r,credential:i})}async executeAuthApproval(r,t){let n=Se(t.options);if(!n.ok)return c(n.error);let s;try{s=await navigator.credentials.get(n.value)}catch(a){return c(_(a))}try{M(s,"get")}catch(a){return c(_(a))}let i;try{i=Q(s)}catch(a){return c(_(a))}return this.apiClient.verifyCrossDeviceAuth({session_id:r,credential:i})}};var ne=class{handlers;constructor(){this.handlers=new Map}on(r,t){let n=this.handlers.get(r);return n||(n=new Set,this.handlers.set(r,n)),n.add(t),()=>{this.off(r,t)}}off(r,t){let n=this.handlers.get(r);n&&(n.delete(t),n.size===0&&this.handlers.delete(r))}emit(r,t){let n=this.handlers.get(r);if(n)for(let s of n)try{s(t)}catch{}}removeAllListeners(){this.handlers.clear()}};var xe="https://api.trymellonauth.com",rr="https://api.trymellonauth.com/v1/telemetry";var tr="trymellon_sandbox_session_token_v1";function nr(e){return{async send(r){let t=JSON.stringify(r);if(typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){navigator.sendBeacon(e,t);return}typeof fetch<"u"&&await fetch(e,{method:"POST",body:t,headers:{"Content-Type":"application/json"},keepalive:!0})}}}function Pe(e,r){return{event:e,latencyMs:r,ok:!0}}var se=class{constructor(r,t,n,s,i){this.apiClient=r;this.eventEmitter=t;this.sandbox=n;this.sandboxToken=s;this.telemetrySender=i}async sandboxAuthResult(r,t){let n="externalUserId"in t?t.externalUserId??t.external_user_id??"sandbox":t.external_user_id??t.externalUserId??"sandbox",s=typeof n=="string"?n:"sandbox";return r==="register"?Promise.resolve(d({success:!0,credentialId:"",status:"sandbox",sessionToken:this.sandboxToken,user:{userId:"sandbox-user",externalUserId:s}})):Promise.resolve(d({authenticated:!0,sessionToken:this.sandboxToken,user:{userId:"sandbox-user",externalUserId:s}}))}async register(r){if(this.sandbox){let s=await this.sandboxAuthResult("register",r);return s.ok&&this.eventEmitter.emit("success",{type:"success",operation:"register",token:s.value.sessionToken,user:s.value.user}),s}let t=Date.now(),n=await Qe(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(Pe("register",Date.now()-t)).catch(()=>{}),n}async authenticate(r){if(this.sandbox){let s=await this.sandboxAuthResult("authenticate",r);return s.ok&&this.eventEmitter.emit("success",{type:"success",operation:"authenticate",token:s.value.sessionToken,user:s.value.user}),s}let t=Date.now(),n=await er(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(Pe("authenticate",Date.now()-t)).catch(()=>{}),n}};async function sr(e,r,t){let n=e.externalUserId??e.external_user_id;if(!n||typeof n!="string"||n.trim()===""){let i=E("externalUserId","must be a non-empty string");return t.emit("error",{type:"error",error:i}),c(i)}if(!e.otp||typeof e.otp!="string"||e.otp.trim().length!==6){let i=E("otp","must be a 6-digit string");return t.emit("error",{type:"error",error:i}),c(i)}let s=await B({operation:"register",eventEmitter:t,start:()=>r.verifyAccountRecoveryOtp(n,e.otp),createOptions:i=>D(i.challenge),invoke:async i=>navigator.credentials.create(i),finish:async(i,a)=>{let l=await r.completeAccountRecovery(i.recovery_session_id,x(a));if(!l.ok)return c(l.error);let{credential_id:m,status:v,session_token:R,user:g,redirect_url:h}=l.value;return d({success:!0,credentialId:m,status:v,sessionToken:R,user:{userId:g.user_id,externalUserId:g.external_user_id,email:g.email,metadata:g.metadata},...h!==void 0&&{redirectUrl:h}})}});return s.ok&&t.emit("success",{type:"success",operation:"register",token:s.value.sessionToken,user:s.value.user}),s}var ie=class{constructor(r,t){this.apiClient=r;this.eventEmitter=t}recover(r){return sr(r,this.apiClient,this.eventEmitter)}};var oe=class e{sandbox;sandboxToken;apiClient;eventEmitter;telemetrySender;crossDeviceManager;authService;recoveryService;onboarding;static create(r){try{let t=r.appId,n=r.publishableKey;if(!t||typeof t!="string"||t.trim()==="")return c(E("appId","must be a non-empty string"));if(!n||typeof n!="string"||n.trim()==="")return c(E("publishableKey","must be a non-empty string"));let s=r.apiBaseUrl??xe;de(s,"apiBaseUrl");let i=r.timeoutMs??3e4;return P(i,"timeoutMs",1e3,3e5),r.maxRetries!==void 0&&P(r.maxRetries,"maxRetries",0,10),r.retryDelayMs!==void 0&&P(r.retryDelayMs,"retryDelayMs",100,1e4),d(new e(r))}catch(t){return ce(t)?c(t):c(E("config",t.message))}}constructor(r){this.sandbox=r.sandbox===!0,this.sandboxToken=this.sandbox&&r.sandboxToken!=null&&r.sandboxToken!==""?r.sandboxToken:tr;let t=r.appId,n=r.publishableKey;if(!t||typeof t!="string"||t.trim()==="")throw E("appId","must be a non-empty string");if(!n||typeof n!="string"||n.trim()==="")throw E("publishableKey","must be a non-empty string");let s=r.apiBaseUrl??xe;de(s,"apiBaseUrl");let i=r.timeoutMs??3e4;P(i,"timeoutMs",1e3,3e5),r.maxRetries!==void 0&&P(r.maxRetries,"maxRetries",0,10),r.retryDelayMs!==void 0&&P(r.retryDelayMs,"retryDelayMs",100,1e4);let a=r.maxRetries??3,l=r.retryDelayMs??1e3,m=new Z(i,a,l,r.logger),v=r.origin??(typeof window<"u"&&window?.location?.origin?window.location.origin:void 0),R={"X-App-Id":t.trim(),Authorization:`Bearer ${n.trim()}`,...v&&{Origin:v}};this.apiClient=new J(m,s,R),this.eventEmitter=new ne,r.enableTelemetry&&(this.telemetrySender=r.telemetrySender??nr(r.telemetryEndpoint??rr)),this.authService=new se(this.apiClient,this.eventEmitter,this.sandbox,this.sandboxToken,this.telemetrySender),this.recoveryService=new ie(this.apiClient,this.eventEmitter),this.onboarding=new re(this.apiClient),this.crossDeviceManager=new te(this.apiClient)}static isSupported(){return L()}async register(r){return this.authService.register(r)}async authenticate(r){return this.authService.authenticate(r)}async validateSession(r){return this.sandbox&&r===this.sandboxToken?Promise.resolve(d({valid:!0,user_id:"sandbox-user",external_user_id:"sandbox",tenant_id:"sandbox-tenant",app_id:"sandbox-app"})):this.apiClient.validateSession(r)}async getStatus(){return Ze()}on(r,t){return this.eventEmitter.on(r,t)}version(){return"2.2.1"}fallback={email:{start:async r=>this.apiClient.startEmailFallback(r),verify:async r=>{let t=await this.apiClient.verifyEmailCode({userId:r.userId,code:r.code,...r.successUrl&&{successUrl:r.successUrl}});return t.ok?d({sessionToken:t.value.sessionToken,...t.value.redirectUrl&&{redirectUrl:t.value.redirectUrl}}):t}}};auth={crossDevice:{init:()=>this.crossDeviceManager.init(),initRegistration:r=>this.crossDeviceManager.initRegistration(r??{}),waitForSession:(r,t,n)=>this.crossDeviceManager.waitForSession(r,t,n),getContext:r=>this.apiClient.getCrossDeviceContext(r),approve:r=>this.crossDeviceManager.approve(r)},recoverAccount:r=>this.recoveryService.recover(r)}};var H=new K.InjectionToken("TRYMELLON_CONFIG"),dr,Me;dr=[(0,K.Injectable)({providedIn:"root"})];var w=class{config=(0,K.inject)(H,{optional:!0});_client=null;get client(){if(this._client==null){if(this.config==null)throw new Error("TryMellonService: provide TRYMELLON_CONFIG (e.g. via provideTryMellonConfig(config))");this._client=new oe(this.config)}return this._client}};Me=Le(null),w=qe(Me,0,"TryMellonService",dr,w),je(Me,1,w);function Wr(e){return{provide:H,useValue:e}}
2
+ "use strict";var A=Object.create;var y=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var w=(r,e)=>(e=Symbol[r])?e:Symbol.for("Symbol."+r),E=r=>{throw TypeError(r)};var F=(r,e,o)=>e in r?y(r,e,{enumerable:!0,configurable:!0,writable:!0,value:o}):r[e]=o;var O=(r,e)=>y(r,"name",{value:e,configurable:!0});var G=(r,e)=>{for(var o in e)y(r,o,{get:e[o],enumerable:!0})},J=(r,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of B(e))!D.call(r,n)&&n!==o&&y(r,n,{get:()=>e[n],enumerable:!(i=j(e,n))||i.enumerable});return r};var K=r=>J(y({},"__esModule",{value:!0}),r);var H=r=>[,,,A(r?.[w("metadata")]??null)],b=["class","method","getter","setter","accessor","field","value","get","set"],u=r=>r!==void 0&&typeof r!="function"?E("Function expected"):r,Q=(r,e,o,i,n)=>({kind:b[r],name:e,metadata:i,addInitializer:l=>o._?E("Already initialized"):n.push(u(l||null))}),U=(r,e)=>F(e,w("metadata"),r[3]),k=(r,e,o,i)=>{for(var n=0,l=r[e>>1],c=l&&l.length;n<c;n++)e&1?l[n].call(o):i=l[n].call(o,i);return i},V=(r,e,o,i,n,l)=>{var c,T,g,M,N,t=e&7,f=!!(e&8),a=!!(e&16),v=t>3?r.length+1:t?f?1:2:0,x=b[t+5],R=t>3&&(r[v-1]=[]),z=r[v]||(r[v]=[]),L=t&&(!a&&!f&&(n=n.prototype),t<5&&(t>3||!a)&&j(t<4?n:{get[o](){return Y(this,l)},set[o](p){return P(this,l,p)}},o));t?a&&t<4&&O(l,(t>2?"set ":t>1?"get ":"")+o):O(n,o);for(var I=i.length-1;I>=0;I--)M=Q(t,o,g={},r[3],z),t&&(M.static=f,M.private=a,N=M.access={has:a?p=>W(n,p):p=>o in p},t^3&&(N.get=a?p=>(t^1?Y:X)(p,n,t^4?l:L.get):p=>p[o]),t>2&&(N.set=a?(p,_)=>P(p,n,_,t^4?l:L.set):(p,_)=>p[o]=_)),T=(0,i[I])(t?t<4?a?l:L[x]:t>4?void 0:{get:L.get,set:L.set}:n,M),g._=1,t^4||T===void 0?u(T)&&(t>4?R.unshift(T):t?a?l=T:L[x]=T:n=T):typeof T!="object"||T===null?E("Object expected"):(u(c=T.get)&&(L.get=c),u(c=T.set)&&(L.set=c),u(c=T.init)&&R.unshift(c));return t||U(r,n),L&&y(n,o,L),a?t^4?l:L:n};var h=(r,e,o)=>e.has(r)||E("Cannot "+o),W=(r,e)=>Object(e)!==e?E('Cannot use the "in" operator on this value'):r.has(e),Y=(r,e,o)=>(h(r,e,"read from private field"),o?o.call(r):e.get(r));var P=(r,e,o,i)=>(h(r,e,"write to private field"),i?i.call(r,o):e.set(r,o),o),X=(r,e,o)=>(h(r,e,"access private method"),o);var $={};G($,{TRYMELLON_CLIENT:()=>d,TryMellonService:()=>m,provideTryMellon:()=>Z});module.exports=K($);var s=require("@angular/core");var d=new s.InjectionToken("TRYMELLON_CLIENT"),q,C;q=[(0,s.Injectable)({providedIn:"root"})];var m=class{_client=(0,s.inject)(d,{optional:!0});get client(){if(this._client==null)throw new Error("TryMellonService: provide TRYMELLON_CLIENT (e.g. via provideTryMellon(client))");return this._client}enroll(e){return this.client.enroll(e)}getContextHash(){return this.client.getContextHash()}};C=H(null),m=V(C,0,"TryMellonService",q,m),k(C,1,m);function Z(r){return{provide:d,useValue:r}}
3
3
  //# sourceMappingURL=angular.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/angular/index.ts","../src/angular/trymellon.service.ts","../src/utils/result.ts","../src/errors.ts","../src/core/validators/helpers.ts","../src/core/validators/register-auth.ts","../src/core/validators/session.ts","../src/core/validators/email.ts","../src/core/validators/onboarding.ts","../src/core/validators/cross-device.ts","../src/core/validators/recovery.ts","../src/core/api.ts","../src/core/fetch-client.ts","../src/utils/base64url.ts","../src/core/webauthn-utils.ts","../src/utils/support.ts","../src/utils/validation.ts","../src/core/ceremony.ts","../src/core/webauthn.ts","../src/core/polling-utils.ts","../src/core/onboarding-manager.ts","../src/core/cross-device-manager.ts","../src/core/events.ts","../src/core/constants.ts","../src/core/adapters/telemetry-sender.ts","../src/core/ports/telemetry.ts","../src/core/services/auth-service.ts","../src/core/recover.ts","../src/core/services/recovery-service.ts","../src/core/trymellon.ts"],"sourcesContent":["import type { Provider } from '@angular/core';\nimport type { TryMellonConfig } from '../types';\nimport { TRYMELLON_CONFIG } from './trymellon.service';\n\nexport { TryMellonService, TRYMELLON_CONFIG } from './trymellon.service';\n\nexport function provideTryMellonConfig(config: TryMellonConfig): Provider {\n return { provide: TRYMELLON_CONFIG, useValue: config } as Provider;\n}\n","import { Injectable, InjectionToken, inject } from '@angular/core';\nimport { TryMellon } from '../core/trymellon';\nimport type { TryMellonConfig } from '../types';\n\nexport const TRYMELLON_CONFIG = new InjectionToken<TryMellonConfig>('TRYMELLON_CONFIG');\n\n@Injectable({ providedIn: 'root' })\nexport class TryMellonService {\n private readonly config = inject(TRYMELLON_CONFIG, { optional: true });\n private _client: TryMellon | null = null;\n\n get client(): TryMellon {\n if (this._client == null) {\n if (this.config == null) {\n throw new Error(\n 'TryMellonService: provide TRYMELLON_CONFIG (e.g. via provideTryMellonConfig(config))'\n );\n }\n this._client = new TryMellon(this.config);\n }\n return this._client;\n }\n}\n","export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport function map<T, E, U>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E> {\n if (result.ok) {\n return ok(mapper(result.value));\n }\n return result;\n}\n\nexport function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F> {\n if (!result.ok) {\n return err(mapper(result.error));\n }\n return result;\n}\n\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (result.ok) {\n return result.value;\n }\n throw result.error;\n}\n","export type TryMellonErrorCode =\n | 'NOT_SUPPORTED'\n | 'USER_CANCELLED'\n | 'PASSKEY_NOT_FOUND'\n | 'SESSION_EXPIRED'\n | 'NETWORK_FAILURE'\n | 'INVALID_ARGUMENT'\n | 'TIMEOUT'\n | 'ABORTED'\n | 'ABORT_ERROR'\n | 'CHALLENGE_MISMATCH'\n | 'UNKNOWN_ERROR';\n\nexport class TryMellonError extends Error {\n readonly code: TryMellonErrorCode;\n readonly details?: unknown;\n readonly isTryMellonError = true;\n\n constructor(code: TryMellonErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TryMellonError';\n this.code = code;\n this.details = details;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TryMellonError);\n }\n }\n}\n\nconst DEFAULT_MESSAGES: Record<TryMellonErrorCode, string> = {\n NOT_SUPPORTED: 'WebAuthn is not supported in this environment',\n USER_CANCELLED: 'User cancelled the operation',\n PASSKEY_NOT_FOUND: 'Passkey not found',\n SESSION_EXPIRED: 'Session has expired',\n NETWORK_FAILURE: 'Network request failed',\n INVALID_ARGUMENT: 'Invalid argument provided',\n TIMEOUT: 'Operation timed out',\n ABORTED: 'Operation was aborted',\n ABORT_ERROR: 'Operation aborted by user or timeout',\n CHALLENGE_MISMATCH: 'This link was already used or expired. Please try again from your computer.',\n UNKNOWN_ERROR: 'An unknown error occurred',\n};\n\nexport function createError(\n code: TryMellonErrorCode,\n message?: string,\n details?: unknown\n): TryMellonError {\n return new TryMellonError(code, message ?? DEFAULT_MESSAGES[code], details);\n}\n\nexport function isTryMellonError(error: unknown): error is TryMellonError {\n return (\n error instanceof TryMellonError ||\n (typeof error === 'object' &&\n error !== null &&\n 'isTryMellonError' in error &&\n (error as TryMellonError).isTryMellonError === true)\n );\n}\n\nexport function createNotSupportedError(): TryMellonError {\n return createError('NOT_SUPPORTED');\n}\n\nexport function createUserCancelledError(): TryMellonError {\n return createError('USER_CANCELLED');\n}\n\nexport function createNetworkError(cause?: Error): TryMellonError {\n return createError('NETWORK_FAILURE', undefined, {\n cause: cause?.message,\n originalError: cause,\n });\n}\n\nexport function createTimeoutError(): TryMellonError {\n return createError('TIMEOUT');\n}\n\nexport function createInvalidArgumentError(field: string, reason: string): TryMellonError {\n return createError('INVALID_ARGUMENT', `Invalid argument: ${field} - ${reason}`, {\n field,\n reason,\n });\n}\n\nexport function createCredentialError(operation: 'create' | 'get'): TryMellonError {\n return createError('UNKNOWN_ERROR', `Failed to ${operation} credential`, { operation });\n}\n\nexport function createEncodingError(type: 'encode' | 'decode'): TryMellonError {\n return createError(\n 'NOT_SUPPORTED',\n `No base64 ${type === 'encode' ? 'encoding' : 'decoding'} available`,\n { type }\n );\n}\n\nexport function validateNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (!value || typeof value !== 'string' || value.trim() === '') {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n}\n\nexport function validateUrl(url: string, fieldName: string): void {\n try {\n const urlObj = new URL(url);\n if (urlObj.protocol !== 'https:' && urlObj.protocol !== 'http:') {\n throw createInvalidArgumentError(fieldName, 'must use http or https protocol');\n }\n } catch (error) {\n if (isTryMellonError(error)) {\n throw error;\n }\n throw createInvalidArgumentError(fieldName, 'must be a valid URL');\n }\n}\n\nexport function validateRange(value: number, fieldName: string, min: number, max: number): void {\n if (!Number.isFinite(value)) {\n throw createInvalidArgumentError(fieldName, 'must be a finite number');\n }\n if (value < min || value > max) {\n throw createInvalidArgumentError(fieldName, `must be between ${min} and ${max}`);\n }\n}\n\nexport function validateBase64Url(s: string, fieldName: string): void {\n if (typeof s !== 'string' || s.length === 0) {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n if (!/^[A-Za-z0-9_-]+$/.test(s)) {\n throw createInvalidArgumentError(fieldName, 'must be a valid base64url string');\n }\n}\n\nconst DOM_EXCEPTION_ERROR_MAP: Record<string, TryMellonErrorCode> = {\n NotAllowedError: 'USER_CANCELLED',\n AbortError: 'ABORTED',\n NotSupportedError: 'NOT_SUPPORTED',\n SecurityError: 'NOT_SUPPORTED',\n InvalidStateError: 'UNKNOWN_ERROR',\n UnknownError: 'UNKNOWN_ERROR',\n};\n\n/**\n * Maps backend API error codes (fintech envelope) to TryMellonErrorCode.\n * Pure, testable. Unknown codes map to UNKNOWN_ERROR.\n * Defensive: non-string input returns UNKNOWN_ERROR (no throw).\n */\nexport function mapBackendErrorCodeToTryMellon(backendCode: string): TryMellonErrorCode {\n if (typeof backendCode !== 'string') return 'UNKNOWN_ERROR';\n const normalized = backendCode.toLowerCase().trim();\n const map: Record<string, TryMellonErrorCode> = {\n challenge_mismatch: 'CHALLENGE_MISMATCH',\n session_expired: 'SESSION_EXPIRED',\n unauthorized: 'SESSION_EXPIRED',\n validation_error: 'INVALID_ARGUMENT',\n invalid_argument: 'INVALID_ARGUMENT',\n user_not_found: 'SESSION_EXPIRED',\n passkey_not_found: 'PASSKEY_NOT_FOUND',\n };\n return map[normalized] ?? 'UNKNOWN_ERROR';\n}\n\nexport function mapWebAuthnError(error: unknown): TryMellonError {\n if (error instanceof DOMException) {\n const name = error.name;\n const message = error.message || 'WebAuthn operation failed';\n const errorCode = DOM_EXCEPTION_ERROR_MAP[name] ?? 'UNKNOWN_ERROR';\n return createError(errorCode, message, { originalError: error });\n }\n\n if (error instanceof Error) {\n return createError('UNKNOWN_ERROR', error.message, { originalError: error });\n }\n\n return createError('UNKNOWN_ERROR', 'An unknown error occurred', {\n originalError: error,\n });\n}\n","import { err, ok, type Result } from '../../utils/result';\nimport { createError, type TryMellonError } from '../../errors';\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nexport function validationError(\n message: string,\n details?: { field?: string; expected?: string; originalData?: unknown }\n): Result<never, TryMellonError> {\n return err(\n createError('UNKNOWN_ERROR', message, {\n ...details,\n originalData: details?.originalData,\n })\n );\n}\n\nexport function required(obj: Record<string, unknown>, key: string): unknown {\n return obj[key];\n}\n\nexport function optionalString(obj: Record<string, unknown>, key: string): string | undefined {\n const v = obj[key];\n return v === undefined ? undefined : typeof v === 'string' ? v : undefined;\n}\n\n// DRY Helpers for common TryMellon objects\n\nexport function validateChallengeRP(rp: unknown, data: unknown): Result<true, TryMellonError> {\n if (!isObject(rp) || !isString(rp.name) || !isString(rp.id)) {\n return validationError('Invalid API response: challenge.rp must have name and id strings', {\n originalData: data,\n });\n }\n return ok(true);\n}\n\nexport function validateChallengeUser(user: unknown, data: unknown): Result<true, TryMellonError> {\n if (\n !isObject(user) ||\n !isString(user.id) ||\n !isString(user.name) ||\n !isString(user.displayName)\n ) {\n return validationError(\n 'Invalid API response: challenge.user must have id, name, displayName strings',\n { originalData: data }\n );\n }\n return ok(true);\n}\n\nexport function validatePubKeyCredParams(\n params: unknown,\n data: unknown\n): Result<true, TryMellonError> {\n if (!isArray(params)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of params) {\n if (!isObject(item) || item.type !== 'public-key' || !isNumber(item.alg)) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n { originalData: data }\n );\n }\n }\n return ok(true);\n}\n\nexport function validateUserEntity(\n user: unknown,\n data: unknown\n): Result<\n { user_id: string; external_user_id: string; email?: string; metadata?: Record<string, unknown> },\n TryMellonError\n> {\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const userId = required(user, 'user_id');\n const externalUserId = required(user, 'external_user_id');\n if (!isString(userId) || !isString(externalUserId)) {\n return validationError(\n 'Invalid API response: user must have user_id and external_user_id strings',\n { originalData: data }\n );\n }\n\n const email = user.email;\n const metadata = user.metadata;\n if (email !== undefined && !isString(email)) {\n return validationError('Invalid API response: user.email must be string', {\n originalData: data,\n });\n }\n if (metadata !== undefined && (typeof metadata !== 'object' || metadata === null)) {\n return validationError('Invalid API response: user.metadata must be object', {\n originalData: data,\n });\n }\n\n return ok({\n user_id: userId,\n external_user_id: externalUserId,\n ...(email !== undefined && { email }),\n ...(metadata !== undefined && { metadata: metadata as Record<string, unknown> }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n RegisterStartResponse,\n AuthStartResponse,\n RegisterFinishResponse,\n AuthFinishResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport {\n isObject,\n isString,\n isNumber,\n isBoolean,\n isArray,\n validationError,\n required,\n validateChallengeRP,\n validateChallengeUser,\n validatePubKeyCredParams,\n validateUserEntity,\n} from './helpers';\n\nexport function validateRegisterStartResponse(\n data: unknown\n): Result<RegisterStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const rpResult = validateChallengeRP(required(challenge, 'rp'), data);\n if (!rpResult.ok) return rpResult;\n\n const userResult = validateChallengeUser(required(challenge, 'user'), data);\n if (!userResult.ok) return userResult;\n\n const challengeStr = required(challenge, 'challenge');\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n\n const pubKeyCredParamsResult = validatePubKeyCredParams(\n required(challenge, 'pubKeyCredParams'),\n data\n );\n if (!pubKeyCredParamsResult.ok) return pubKeyCredParamsResult;\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const excludeCredentials = challenge.excludeCredentials;\n if (excludeCredentials !== undefined) {\n if (!isArray(excludeCredentials)) {\n return validationError('Invalid API response: excludeCredentials must be array', {\n originalData: data,\n });\n }\n for (const c of excludeCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: excludeCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const authenticatorSelection = challenge.authenticatorSelection;\n if (authenticatorSelection !== undefined && !isObject(authenticatorSelection)) {\n return validationError('Invalid API response: authenticatorSelection must be object', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n challenge: {\n rp: challenge.rp as RegisterStartResponse['challenge']['rp'],\n user: challenge.user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams:\n challenge.pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n ...(timeout !== undefined && { timeout }),\n ...(excludeCredentials !== undefined && {\n excludeCredentials:\n excludeCredentials as RegisterStartResponse['challenge']['excludeCredentials'],\n }),\n ...(authenticatorSelection !== undefined && {\n authenticatorSelection:\n authenticatorSelection as RegisterStartResponse['challenge']['authenticatorSelection'],\n }),\n },\n });\n}\n\nexport function validateAuthStartResponse(\n data: unknown\n): Result<AuthStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const ch = required(challenge, 'challenge');\n const rpId = required(challenge, 'rpId');\n const allowCredentials = challenge.allowCredentials;\n if (!isString(ch)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isString(rpId)) {\n return validationError('Invalid API response: challenge.rpId must be string', {\n originalData: data,\n });\n }\n if (allowCredentials !== undefined && !isArray(allowCredentials)) {\n return validationError('Invalid API response: allowCredentials must be array', {\n originalData: data,\n });\n }\n if (allowCredentials) {\n for (const c of allowCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: allowCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const userVerification = challenge.userVerification;\n if (\n userVerification !== undefined &&\n !['required', 'preferred', 'discouraged'].includes(String(userVerification))\n ) {\n return validationError(\n 'Invalid API response: userVerification must be required|preferred|discouraged',\n {\n originalData: data,\n }\n );\n }\n\n return ok({\n session_id,\n challenge: {\n challenge: ch,\n rpId,\n allowCredentials:\n (allowCredentials as AuthStartResponse['challenge']['allowCredentials']) ?? [],\n ...(timeout !== undefined && { timeout }),\n ...(userVerification !== undefined && {\n userVerification: userVerification as AuthStartResponse['challenge']['userVerification'],\n }),\n },\n });\n}\n\nexport function validateRegisterFinishResponse(\n data: unknown\n): Result<RegisterFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const credential_id = required(data, 'credential_id');\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n const redirect_url = data.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n credential_id,\n status,\n session_token,\n user: userResult.value,\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n\nexport function validateAuthFinishResponse(\n data: unknown\n): Result<AuthFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const authenticated = required(data, 'authenticated');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const signals = required(data, 'signals');\n\n if (!isBoolean(authenticated)) {\n return validationError('Invalid API response: authenticated must be boolean', {\n field: 'authenticated',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n if (signals !== undefined && !isObject(signals)) {\n return validationError('Invalid API response: signals must be object', {\n originalData: data,\n });\n }\n\n const redirect_url = data.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n authenticated,\n session_token,\n user: userResult.value,\n signals: signals as AuthFinishResponse['signals'],\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { SessionValidateResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isBoolean, required, validationError } from './helpers';\n\nexport function validateSessionValidateResponse(\n data: unknown\n): Result<SessionValidateResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const valid = required(data, 'valid');\n const user_id = required(data, 'user_id');\n const external_user_id = required(data, 'external_user_id');\n const tenant_id = required(data, 'tenant_id');\n const app_id = required(data, 'app_id');\n\n if (!isBoolean(valid)) {\n return validationError('Invalid API response: valid must be boolean', {\n field: 'valid',\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n field: 'user_id',\n originalData: data,\n });\n }\n if (!isString(external_user_id)) {\n return validationError('Invalid API response: external_user_id must be string', {\n field: 'external_user_id',\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n field: 'tenant_id',\n originalData: data,\n });\n }\n if (!isString(app_id)) {\n return validationError('Invalid API response: app_id must be string', {\n field: 'app_id',\n originalData: data,\n });\n }\n\n return ok({\n valid,\n user_id,\n external_user_id,\n tenant_id,\n app_id,\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\n\nexport function validateEmailVerifyResponse(\n data: unknown\n): Result<{ sessionToken: string; redirectUrl?: string }, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const raw =\n (data as Record<string, unknown>).session_token ??\n (data as Record<string, unknown>).sessionToken;\n if (!isString(raw)) {\n return validationError('Invalid API response: session_token/sessionToken must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n const redirect_url = (data as Record<string, unknown>).redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n originalData: data,\n });\n }\n\n return ok({\n sessionToken: raw,\n ...(redirect_url !== undefined && { redirectUrl: redirect_url }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterResponse,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteResponse,\n RegisterStartResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isNumber, isArray, required, validationError } from './helpers';\n\nconst ONBOARDING_STATUSES = ['pending_passkey', 'pending_data', 'completed'] as const;\nconst REGISTER_PASSKEY_STATUSES = ['pending_data', 'completed'] as const;\n\nexport function validateOnboardingStartResponse(\n data: unknown\n): Result<OnboardingStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n field: 'onboarding_url',\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n field: 'expires_in',\n originalData: data,\n });\n }\n\n return ok({ session_id, onboarding_url, expires_in });\n}\n\nexport function validateOnboardingStatusResponse(\n data: unknown\n): Result<OnboardingStatusResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (\n !isString(status) ||\n !ONBOARDING_STATUSES.includes(status as (typeof ONBOARDING_STATUSES)[number])\n ) {\n return validationError(\n 'Invalid API response: status must be pending_passkey|pending_data|completed',\n {\n field: 'status',\n originalData: data,\n }\n );\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as OnboardingStatusResponse['status'],\n onboarding_url,\n expires_in,\n });\n}\n\n/** Response may include optional challenge for same-device passkey registration */\nexport type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {\n challenge?: RegisterStartResponse['challenge'];\n};\n\nexport function validateOnboardingRegisterResponse(\n data: unknown\n): Result<OnboardingRegisterResponseWithChallenge, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (status !== 'pending_passkey') {\n return validationError('Invalid API response: status must be pending_passkey', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n\n const challenge = data.challenge;\n let parsedChallenge: RegisterStartResponse['challenge'] | undefined;\n if (challenge !== undefined) {\n const chResult = validateOnboardingChallenge(challenge);\n if (!chResult.ok) return chResult;\n parsedChallenge = chResult.value;\n }\n\n return ok({\n session_id,\n status: 'pending_passkey',\n onboarding_url,\n ...(parsedChallenge !== undefined && { challenge: parsedChallenge }),\n });\n}\n\nfunction validateOnboardingChallenge(\n data: unknown\n): Result<RegisterStartResponse['challenge'], TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: challenge must be object', {\n originalData: data,\n });\n }\n\n const rp = required(data, 'rp');\n const user = required(data, 'user');\n const challengeStr = required(data, 'challenge');\n const pubKeyCredParams = required(data, 'pubKeyCredParams');\n\n if (\n !isObject(rp) ||\n !isString((rp as Record<string, unknown>).name) ||\n !isString((rp as Record<string, unknown>).id)\n ) {\n return validationError('Invalid API response: challenge.rp must have name and id', {\n originalData: data,\n });\n }\n if (\n !isObject(user) ||\n !isString((user as Record<string, unknown>).id) ||\n !isString((user as Record<string, unknown>).name) ||\n !isString((user as Record<string, unknown>).displayName)\n ) {\n return validationError('Invalid API response: challenge.user must have id, name, displayName', {\n originalData: data,\n });\n }\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isArray(pubKeyCredParams)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of pubKeyCredParams) {\n if (\n !isObject(item) ||\n (item as Record<string, unknown>).type !== 'public-key' ||\n !isNumber((item as Record<string, unknown>).alg)\n ) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n {\n originalData: data,\n }\n );\n }\n }\n\n return ok({\n rp: rp as RegisterStartResponse['challenge']['rp'],\n user: user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams: pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n });\n}\n\nexport function validateOnboardingRegisterPasskeyResponse(\n data: unknown\n): Result<OnboardingRegisterPasskeyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (\n !isString(status) ||\n !REGISTER_PASSKEY_STATUSES.includes(status as (typeof REGISTER_PASSKEY_STATUSES)[number])\n ) {\n return validationError('Invalid API response: status must be pending_data|completed', {\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n status: status as OnboardingRegisterPasskeyResponse['status'],\n user_id,\n tenant_id,\n });\n}\n\nexport function validateOnboardingCompleteResponse(\n data: unknown\n): Result<OnboardingCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n const session_token = required(data, 'session_token');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (status !== 'completed') {\n return validationError('Invalid API response: status must be completed', {\n originalData: data,\n });\n }\n if (!isString(user_id) || !isString(tenant_id) || !isString(session_token)) {\n return validationError(\n 'Invalid API response: user_id, tenant_id, session_token must be strings',\n { originalData: data }\n );\n }\n\n return ok({\n session_id,\n status: 'completed',\n user_id,\n tenant_id,\n session_token,\n });\n}\n","import { ok } from '../../utils/result';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n} from '../../types';\n\n/**\n * Validates the response for cross-device verify and verify-registration endpoints.\n * Backend returns 204 No Content; body may be undefined, null, or empty object.\n * Accepts only those; rejects any other shape to detect unexpected API responses.\n */\nexport function validateCrossDeviceVerifyResponse(data: unknown): Result<void, TryMellonError> {\n if (data === undefined || data === null) {\n return ok(undefined);\n }\n if (isObject(data) && Object.keys(data).length === 0) {\n return ok(undefined);\n }\n return validationError('Invalid API response: expected empty body (204)', {\n originalData: data,\n });\n}\n\nfunction isCreationOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return (\n typeof o.challenge === 'string' &&\n o.rp != null &&\n typeof o.rp === 'object' &&\n o.user != null &&\n typeof o.user === 'object' &&\n Array.isArray((o as { pubKeyCredParams?: unknown }).pubKeyCredParams)\n );\n}\n\nfunction isRequestOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return typeof o.challenge === 'string' && typeof o.rpId === 'string';\n}\n\n/**\n * Accepts either the unwrapped payload { session_id, qr_url, expires_at } or the fintech\n * envelope { ok: true, resultado: { session_id, qr_url, expires_at } } so the flow works\n * regardless of whether the fetch-client unwraps before calling this validator.\n */\nexport function validateCrossDeviceInitResponse(\n data: unknown\n): Result<CrossDeviceInitResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const payload =\n 'resultado' in data && isObject((data as { resultado: unknown }).resultado)\n ? (data as { resultado: Record<string, unknown> }).resultado\n : data;\n\n const session_id = payload.session_id;\n const qr_url = payload.qr_url;\n const expires_at = payload.expires_at;\n const polling_token = payload.polling_token;\n\n if (\n !isString(session_id) ||\n !isString(qr_url) ||\n !isString(expires_at) ||\n !isString(polling_token)\n ) {\n return validationError('Invalid API response: missing required fields', { originalData: data });\n }\n\n const result: CrossDeviceInitResult = {\n session_id,\n qr_url,\n expires_at,\n polling_token,\n };\n if (payload.external_user_id !== undefined && isString(payload.external_user_id)) {\n result.external_user_id = payload.external_user_id;\n }\n return ok(result);\n}\n\n/**\n * Accepts either the unwrapped payload { status, user_id?, session_token?, redirect_url? } or the\n * fintech envelope { ok: true, resultado: { ... } } so the flow works regardless of unwrapping.\n */\nexport function validateCrossDeviceStatusResponse(\n data: unknown\n): Result<CrossDeviceStatusResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const payload =\n 'resultado' in data && isObject((data as { resultado: unknown }).resultado)\n ? (data as { resultado: Record<string, unknown> }).resultado\n : data;\n\n const status = payload.status;\n if (!isString(status) || !['pending', 'authenticated', 'completed'].includes(status)) {\n return validationError('Invalid API response: invalid status', { originalData: data });\n }\n\n const user_id = payload.user_id;\n const session_token = payload.session_token;\n const redirect_url = payload.redirect_url;\n\n if (user_id !== undefined && !isString(user_id)) {\n return validationError('Invalid API response: user_id must be a string when present', {\n originalData: data,\n });\n }\n if (session_token !== undefined && !isString(session_token)) {\n return validationError('Invalid API response: session_token must be a string when present', {\n originalData: data,\n });\n }\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be a string when present', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as CrossDeviceStatusResult['status'],\n user_id: user_id as string | undefined,\n session_token: session_token as string | undefined,\n redirect_url: redirect_url as string | undefined,\n });\n}\n\nexport function validateCrossDeviceContextResponse(\n data: unknown\n): Result<CrossDeviceContextResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const rawType = data.type;\n const type =\n rawType === 'registration' ? 'registration' : rawType === 'auth' ? 'auth' : ('auth' as const);\n\n const options = data.options;\n if (!isObject(options)) {\n return validationError('Invalid API response: options are required', { originalData: data });\n }\n\n const MAX_CONTEXT_LENGTH = 200;\n const approval_context = optionalContextString(data.approval_context, MAX_CONTEXT_LENGTH);\n const application_name = optionalContextString(data.application_name, MAX_CONTEXT_LENGTH);\n if (approval_context === false || application_name === false) {\n return validationError(\n 'Invalid API response: approval_context/application_name must be string max 200 chars',\n {\n originalData: data,\n }\n );\n }\n\n const extra: { approval_context?: string; application_name?: string } = {};\n if (typeof approval_context === 'string') extra.approval_context = approval_context;\n if (typeof application_name === 'string') extra.application_name = application_name;\n\n if (type === 'registration') {\n if (!isCreationOptionsShape(options)) {\n return validationError(\n 'Invalid API response: registration options must have challenge, rp, user, pubKeyCredParams',\n { originalData: data }\n );\n }\n return ok({\n type: 'registration',\n options,\n ...extra,\n } as CrossDeviceContextResult);\n }\n\n if (!isRequestOptionsShape(options)) {\n return validationError('Invalid API response: auth options must have challenge and rpId', {\n originalData: data,\n });\n }\n return ok({ type: 'auth', options, ...extra } as CrossDeviceContextResult);\n}\n\n/** Returns string if valid (optional, max len), undefined if missing, false if invalid. */\nfunction optionalContextString(value: unknown, maxLength: number): string | undefined | false {\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') return false;\n if (value.length > maxLength) return false;\n return value;\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { RecoveryVerifyResponse, RecoveryCompleteResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateRecoveryVerifyResponse(\n data: unknown\n): Result<RecoveryVerifyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const challenge = required(data, 'challenge');\n const recovery_session_id = required(data, 'recovery_session_id');\n\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n if (!isString(recovery_session_id)) {\n return validationError('Invalid API response: recovery_session_id must be string', {\n field: 'recovery_session_id',\n originalData: data,\n });\n }\n\n return ok({\n challenge: challenge as Record<string, unknown>,\n recovery_session_id,\n });\n}\n\nexport function validateRecoveryCompleteResponse(\n data: unknown\n): Result<RecoveryCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const credential_id = required(data, 'credential_id');\n\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const user_id = required(user, 'user_id');\n if (!isString(user_id)) {\n return validationError('Invalid API response: user.user_id must be string', {\n field: 'user.user_id',\n originalData: data,\n });\n }\n\n const dataObj = data as Record<string, unknown>;\n const redirect_url = dataObj.redirect_url;\n if (redirect_url !== undefined && !isString(redirect_url)) {\n return validationError('Invalid API response: redirect_url must be string', {\n field: 'redirect_url',\n originalData: data,\n });\n }\n\n const userObj = user as Record<string, unknown>;\n return ok({\n status,\n session_token,\n credential_id,\n user: {\n user_id,\n external_user_id: isString(userObj.external_user_id) ? userObj.external_user_id : undefined,\n email: isString(userObj.email) ? userObj.email : undefined,\n metadata: isObject(userObj.metadata)\n ? (userObj.metadata as Record<string, unknown>)\n : undefined,\n },\n ...(redirect_url !== undefined && { redirect_url }),\n });\n}\n","import type { HttpClient } from './http-client';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport {\n validateRegisterStartResponse,\n validateAuthStartResponse,\n validateRegisterFinishResponse,\n validateAuthFinishResponse,\n validateSessionValidateResponse,\n validateEmailVerifyResponse,\n validateOnboardingStartResponse,\n validateOnboardingStatusResponse,\n validateOnboardingRegisterResponse,\n validateOnboardingRegisterPasskeyResponse,\n validateOnboardingCompleteResponse,\n validateCrossDeviceInitResponse,\n validateCrossDeviceStatusResponse,\n validateCrossDeviceContextResponse,\n validateCrossDeviceVerifyResponse,\n validateRecoveryVerifyResponse,\n validateRecoveryCompleteResponse,\n} from './validators';\nimport type {\n RegisterStartRequest,\n RegisterStartResponse,\n AuthStartRequest,\n AuthStartResponse,\n RegisterFinishRequest,\n RegisterFinishResponse,\n AuthFinishRequest,\n AuthFinishResponse,\n SessionValidateResponse,\n OnboardingStartRequest,\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterPasskeyRequest,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteRequest,\n OnboardingCompleteResponse,\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n CrossDeviceVerifyRequest,\n CrossDeviceVerifyRegistrationRequest,\n RecoveryVerifyResponse,\n RecoveryCompleteResponse,\n} from '../types';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nexport class ApiClient {\n constructor(\n private readonly httpClient: HttpClient,\n private readonly baseUrl: string,\n private readonly defaultHeaders: Record<string, string> = {}\n ) {}\n\n private mergeHeaders(extra?: Record<string, string>): Record<string, string> {\n return { ...this.defaultHeaders, ...extra };\n }\n\n private async post<Req, Res>(\n path: string,\n body: Req,\n validate: (data: unknown) => Result<Res, TryMellonError>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.post<unknown>(url, body, this.mergeHeaders());\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n private async get<Res>(\n path: string,\n validate: (data: unknown) => Result<Res, TryMellonError>,\n headers?: Record<string, string>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.get<unknown>(url, this.mergeHeaders(headers));\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n async startRegister(\n request: RegisterStartRequest\n ): Promise<Result<RegisterStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/start', request, validateRegisterStartResponse);\n }\n\n async startAuth(request: AuthStartRequest): Promise<Result<AuthStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/start', request, validateAuthStartResponse);\n }\n\n async finishRegister(\n request: RegisterFinishRequest\n ): Promise<Result<RegisterFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/finish', request, validateRegisterFinishResponse);\n }\n\n async finishAuthentication(\n request: AuthFinishRequest\n ): Promise<Result<AuthFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/finish', request, validateAuthFinishResponse);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n return this.get('/v1/sessions/validate', validateSessionValidateResponse, {\n Authorization: `Bearer ${sessionToken}`,\n });\n }\n\n async startEmailFallback(options: {\n userId: string;\n email: string;\n }): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/fallback/email/start`;\n const result = await this.httpClient.post<unknown>(\n url,\n { userId: options.userId, email: options.email },\n this.mergeHeaders()\n );\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyEmailCode(options: {\n userId: string;\n code: string;\n successUrl?: string;\n }): Promise<Result<{ sessionToken: string; redirectUrl?: string }, TryMellonError>> {\n const body: Record<string, unknown> = { userId: options.userId, code: options.code };\n if (options.successUrl) body.success_url = options.successUrl;\n return this.post('/v1/fallback/email/verify', body, validateEmailVerifyResponse);\n }\n\n async startOnboarding(\n request: OnboardingStartRequest\n ): Promise<Result<OnboardingStartResponse, TryMellonError>> {\n return this.post('/v1/onboarding/start', request, validateOnboardingStartResponse);\n }\n\n async getOnboardingStatus(\n sessionId: string\n ): Promise<Result<OnboardingStatusResponse, TryMellonError>> {\n return this.get(`/v1/onboarding/${sessionId}/status`, validateOnboardingStatusResponse);\n }\n\n async getOnboardingRegister(\n sessionId: string\n ): Promise<Result<OnboardingRegisterResponseWithChallenge, TryMellonError>> {\n return this.get(`/v1/onboarding/${sessionId}/register`, validateOnboardingRegisterResponse);\n }\n\n async registerOnboardingPasskey(\n sessionId: string,\n request: OnboardingRegisterPasskeyRequest\n ): Promise<Result<OnboardingRegisterPasskeyResponse, TryMellonError>> {\n return this.post(\n `/v1/onboarding/${sessionId}/register-passkey`,\n request,\n validateOnboardingRegisterPasskeyResponse\n );\n }\n\n async completeOnboarding(\n sessionId: string,\n request: OnboardingCompleteRequest\n ): Promise<Result<OnboardingCompleteResponse, TryMellonError>> {\n return this.post(\n `/v1/onboarding/${sessionId}/complete`,\n request,\n validateOnboardingCompleteResponse\n );\n }\n\n async initCrossDeviceAuth(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post('/v1/auth/cross-device/init', {}, validateCrossDeviceInitResponse);\n }\n\n async initCrossDeviceRegistration(options?: {\n externalUserId?: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n const trimmed =\n typeof options?.externalUserId === 'string' ? options.externalUserId.trim() : '';\n const body = trimmed.length > 0 ? { external_user_id: trimmed } : {};\n return this.post(\n '/v1/auth/cross-device/init-registration',\n body,\n validateCrossDeviceInitResponse\n );\n }\n\n async getCrossDeviceStatus(\n sessionId: string,\n pollingToken?: string | null\n ): Promise<Result<CrossDeviceStatusResult, TryMellonError>> {\n const headers: Record<string, string> = {};\n if (typeof pollingToken === 'string' && pollingToken.length > 0) {\n headers['X-Polling-Token'] = pollingToken;\n }\n return this.get(\n `/v1/auth/cross-device/status/${sessionId}`,\n validateCrossDeviceStatusResponse,\n Object.keys(headers).length > 0 ? headers : undefined\n );\n }\n\n /**\n * Fetches WebAuthn options for the cross-device session.\n * Contract: response is CrossDeviceContextResult (auth | registration).\n * Use result.value.type to branch: 'auth' → credentials.get + verify;\n * 'registration' → credentials.create + verify-registration.\n */\n async getCrossDeviceContext(\n sessionId: string\n ): Promise<Result<CrossDeviceContextResult, TryMellonError>> {\n return this.get(\n `/v1/auth/cross-device/context/${sessionId}`,\n validateCrossDeviceContextResponse\n );\n }\n\n async verifyCrossDeviceAuth(\n request: CrossDeviceVerifyRequest\n ): Promise<Result<void, TryMellonError>> {\n return this.post('/v1/auth/cross-device/verify', request, validateCrossDeviceVerifyResponse);\n }\n\n async verifyCrossDeviceRegistration(\n request: CrossDeviceVerifyRegistrationRequest\n ): Promise<Result<void, TryMellonError>> {\n return this.post(\n '/v1/auth/cross-device/verify-registration',\n request,\n validateCrossDeviceVerifyResponse\n );\n }\n\n async verifyAccountRecoveryOtp(\n externalUserId: string,\n otp: string\n ): Promise<Result<RecoveryVerifyResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/verify',\n { external_id: externalUserId, otp },\n validateRecoveryVerifyResponse\n );\n }\n\n async completeAccountRecovery(\n recoverySessionId: string,\n credential: Record<string, unknown>\n ): Promise<Result<RecoveryCompleteResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/complete',\n { recovery_session_id: recoverySessionId, credential },\n validateRecoveryCompleteResponse\n );\n }\n}\n","import type { HttpClient } from './http-client';\nimport type { Logger } from './ports/logger';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport {\n createError,\n mapBackendErrorCodeToTryMellon,\n type TryMellonError,\n type TryMellonErrorCode,\n} from '../errors';\n\n/** Fintech success envelope: { ok: true, resultado: T } */\nfunction isEnvelopeSuccess(data: unknown): data is { ok: true; resultado: unknown } {\n return (\n typeof data === 'object' &&\n data !== null &&\n (data as Record<string, unknown>).ok === true &&\n 'resultado' in (data as Record<string, unknown>)\n );\n}\n\n/** Fintech error envelope: { ok: false, error: { code, message } } */\nfunction isEnvelopeError(\n data: unknown\n): data is { ok: false; error: { code: string; message: string; details?: unknown } } {\n if (typeof data !== 'object' || data === null) return false;\n const o = data as Record<string, unknown>;\n if (o.ok !== false || !o.error || typeof o.error !== 'object') return false;\n const err = o.error as Record<string, unknown>;\n return typeof err.code === 'string' && typeof err.message === 'string';\n}\n\n/**\n * Pure function: parses HTTP error body (fintech envelope or fallbacks) into message and code.\n * Concentrates all error-body parsing in one place for testability and single responsibility.\n */\nexport function parseHttpErrorBody(\n errorData: unknown,\n statusText: string\n): { message: string; code: TryMellonErrorCode } {\n if (isEnvelopeError(errorData)) {\n return {\n message: errorData.error.message,\n code: mapBackendErrorCodeToTryMellon(errorData.error.code),\n };\n }\n const body = errorData as\n | { message?: string; error?: string | { code?: string; message?: string } }\n | undefined;\n const errObj = body?.error;\n if (\n typeof errObj === 'object' &&\n errObj !== null &&\n 'code' in errObj &&\n typeof (errObj as { code: string }).code === 'string'\n ) {\n return {\n message: (errObj as { message?: string }).message ?? body?.message ?? statusText,\n code: mapBackendErrorCodeToTryMellon((errObj as { code: string }).code),\n };\n }\n const message = body?.message ?? statusText;\n const rawCode = body?.error;\n const code =\n typeof rawCode === 'string'\n ? mapBackendErrorCodeToTryMellon(rawCode)\n : rawCode === undefined\n ? 'NETWORK_FAILURE'\n : mapBackendErrorCodeToTryMellon(String(rawCode));\n return { message, code };\n}\n\nconst RETRY_DELAY_CAP_MS = 30_000;\n\n/**\n * Generates a unique request ID. Uses globalThis.crypto.randomUUID only (Elite: no Node crypto).\n * @throws Error when Web Crypto API is not available (Edge/browser must provide it).\n */\nfunction generateRequestId(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID();\n }\n throw new Error('Web Crypto API is required but not available.');\n}\n\n/**\n * Exponential backoff delay for a given attempt (0-based).\n * Cap at RETRY_DELAY_CAP_MS.\n */\nexport function getRetryDelayMs(attempt: number, baseMs: number): number {\n const delay = baseMs * Math.pow(2, attempt);\n return Math.min(delay, RETRY_DELAY_CAP_MS);\n}\n\nfunction shouldRetryOnStatus(method: string, status: number): boolean {\n if (method !== 'GET') return false;\n return status >= 500 || status === 429;\n}\n\nexport class FetchHttpClient implements HttpClient {\n constructor(\n private readonly timeoutMs: number,\n private readonly maxRetries: number = 0,\n private readonly retryDelayMs: number = 1000,\n private readonly logger?: Logger\n ) {}\n\n async get<T>(url: string, headers?: Record<string, string>): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, { method: 'GET', headers });\n }\n\n async post<T>(\n url: string,\n body: unknown,\n headers?: Record<string, string>\n ): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: { 'Content-Type': 'application/json', ...headers },\n });\n }\n\n private async request<T>(url: string, config: RequestInit): Promise<Result<T, TryMellonError>> {\n const method = (config.method ?? 'GET').toUpperCase();\n const requestId = generateRequestId();\n const headers = new Headers(config.headers as HeadersInit);\n headers.set('X-Request-Id', requestId);\n\n if (this.logger) {\n this.logger.debug('request', { requestId, url, method });\n }\n\n let lastError: TryMellonError | Error | unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...config,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorData: unknown;\n try {\n errorData = await response.json();\n } catch {\n // Ignore JSON parse error\n }\n\n const { message, code } = parseHttpErrorBody(errorData, response.statusText);\n const errResult = createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: errorData,\n });\n\n if (shouldRetryOnStatus(method, response.status) && attempt < this.maxRetries) {\n lastError = errResult;\n clearTimeout(timeoutId);\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n continue;\n }\n\n return err(errResult);\n }\n\n if (response.status === 204) {\n return ok(undefined as T);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n return ok(undefined as T);\n }\n const raw = (await response.json()) as unknown;\n if (isEnvelopeSuccess(raw)) {\n return ok((raw as { ok: true; resultado: T }).resultado);\n }\n const o = raw as Record<string, unknown>;\n if (typeof raw === 'object' && raw !== null && o.ok === true && !('resultado' in o)) {\n return ok(undefined as T);\n }\n if (isEnvelopeError(raw)) {\n const { message, code } = parseHttpErrorBody(raw, response.statusText);\n return err(\n createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: raw,\n })\n );\n }\n return ok(raw as T);\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n lastError = error;\n const isGet = method === 'GET';\n if (isGet && attempt < this.maxRetries) {\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n } else {\n break;\n }\n }\n }\n\n if (lastError instanceof Error && lastError.name === 'AbortError') {\n return err(createError('TIMEOUT', 'Request timed out', { requestId }));\n }\n\n return err(\n createError(\n 'NETWORK_FAILURE',\n lastError instanceof Error ? lastError.message : 'Request failed',\n { requestId, cause: lastError }\n )\n );\n }\n}\n","import { createEncodingError } from '../errors';\n\n/**\n * Encodes an ArrayBuffer to base64url using globalThis.btoa (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when btoa is unavailable\n */\nexport function base64UrlEncode(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join('');\n\n if (typeof globalThis.btoa === 'undefined') {\n throw createEncodingError('encode');\n }\n const base64 = globalThis.btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Decodes a base64url string to Uint8Array using globalThis.atob (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when atob is unavailable\n */\nexport function base64UrlDecode(s: string): Uint8Array {\n if (typeof globalThis.atob === 'undefined') {\n throw createEncodingError('decode');\n }\n\n const base64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const padding = base64.length % 4;\n const padded = padding === 0 ? base64 : base64 + '='.repeat(4 - padding);\n const binary = globalThis.atob(padded);\n\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n\n/** Decodes base64url to ArrayBuffer (delegates to base64UrlDecode). */\nexport function base64UrlDecodeToArrayBuffer(s: string): ArrayBuffer {\n const bytes = base64UrlDecode(s);\n const buffer = new ArrayBuffer(bytes.length);\n new Uint8Array(buffer).set(bytes);\n return buffer;\n}\n","import { createError } from '../errors';\nimport { base64UrlEncode } from '../utils/base64url';\nimport type { RegisterFinishRequest, AuthFinishRequest } from '../types';\n\ntype SerializedCredentialForRegister = RegisterFinishRequest['credential'];\ntype SerializedCredentialForAuth = AuthFinishRequest['credential'];\n\n/**\n * Type guard to verify whether a credential response is valid.\n */\nfunction isValidCredentialResponse(\n response: unknown\n): response is AuthenticatorAssertionResponse | AuthenticatorAttestationResponse {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'clientDataJSON' in response &&\n response.clientDataJSON instanceof ArrayBuffer\n );\n}\n\n/**\n * Serializes a credential for registration (finish).\n * Includes attestationObject required for registration verification.\n *\n * @param credential - WebAuthn credential from navigator.credentials.create()\n * @returns Serialized credential in Base64URL format\n * @throws {TryMellonError} If the credential does not have the expected structure for registration\n */\nexport function serializeCredentialForRegister(\n credential: PublicKeyCredential\n): SerializedCredentialForRegister {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('attestationObject' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for register: attestationObject is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const attestationObject = (response as AuthenticatorAttestationResponse).attestationObject;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n clientDataJSON: base64UrlEncode(clientDataJSON),\n attestationObject: base64UrlEncode(attestationObject),\n },\n type: 'public-key',\n };\n}\n\n/**\n * Serializes a credential for authentication (finish).\n * Includes authenticatorData, signature, and optionally userHandle.\n *\n * @param credential - WebAuthn credential from navigator.credentials.get()\n * @returns Serialized credential in Base64URL format\n * @throws {TryMellonError} If the credential does not have the expected structure for authentication\n */\nexport function serializeCredentialForAuth(\n credential: PublicKeyCredential\n): SerializedCredentialForAuth {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('authenticatorData' in response) || !('signature' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for auth: authenticatorData or signature is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const authenticatorData = (response as AuthenticatorAssertionResponse).authenticatorData;\n const signature = (response as AuthenticatorAssertionResponse).signature;\n const userHandle = (response as AuthenticatorAssertionResponse).userHandle;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n authenticatorData: base64UrlEncode(authenticatorData),\n clientDataJSON: base64UrlEncode(clientDataJSON),\n signature: base64UrlEncode(signature),\n ...(userHandle && { userHandle: base64UrlEncode(userHandle) }),\n },\n type: 'public-key',\n };\n}\n","import type { ClientStatus } from '../types';\n\nexport function isWebAuthnSupported(): boolean {\n try {\n if (typeof navigator === 'undefined' || !navigator.credentials) {\n return false;\n }\n\n if (typeof PublicKeyCredential === 'undefined') {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n try {\n if (!isWebAuthnSupported()) {\n return false;\n }\n\n if (typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable !== 'function') {\n return false;\n }\n\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\nexport async function getClientStatus(): Promise<ClientStatus> {\n const isPasskeySupported = isWebAuthnSupported();\n const platformAuthenticatorAvailable = await isPlatformAuthenticatorAvailable();\n\n return {\n isPasskeySupported,\n platformAuthenticatorAvailable,\n recommendedFlow: isPasskeySupported ? 'passkey' : 'fallback',\n };\n}\n","import { createCredentialError } from '../errors';\n\nexport function validateCredentialStructure(\n credential: unknown,\n operation: 'create' | 'get' = 'create'\n): asserts credential is PublicKeyCredential {\n if (\n !credential ||\n typeof credential !== 'object' ||\n !('id' in credential) ||\n !('rawId' in credential) ||\n !('response' in credential)\n ) {\n throw createCredentialError(operation);\n }\n}\n","import type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { isWebAuthnSupported } from '../utils/support';\nimport type { EventEmitter } from './events';\nimport type { TryMellonError } from '../errors';\nimport { mapWebAuthnError, createNotSupportedError, createInvalidArgumentError } from '../errors';\nimport { validateCredentialStructure } from '../utils/validation';\n\nexport type CeremonyOperation = 'register' | 'authenticate';\n\nexport interface InvokeCeremonyContext<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n> {\n operation: CeremonyOperation;\n eventEmitter: EventEmitter;\n start: () => Promise<Result<TStartResult, TryMellonError>>;\n createOptions: (startResult: TStartResult) => Result<TCeremonyOptions, TryMellonError>;\n invoke: (options: TCeremonyOptions) => Promise<Credential | null>;\n finish: (\n startResult: TStartResult,\n credential: PublicKeyCredential\n ) => Promise<Result<TFinishResult, TryMellonError>>;\n}\n\n/**\n * Orchestrates a generic WebAuthn flow (Ceremony) to remove duplicated code in the SDK.\n * Encapsulates start call, options creation, browser credentials API invocation,\n * base structure validation, and finish call.\n */\nexport async function invokeCeremony<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n>(\n context: InvokeCeremonyContext<TStartResult, TFinishResult, TCeremonyOptions>\n): Promise<Result<TFinishResult, TryMellonError>> {\n const { operation, eventEmitter, start, createOptions, invoke, finish } = context;\n\n try {\n eventEmitter.emit('start', { type: 'start', operation });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 1. Obtener challenge del servidor\n const startResult = await start();\n if (!startResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: startResult.error });\n return err(startResult.error);\n }\n\n // 2. Create options\n const optionsResult = createOptions(startResult.value);\n if (!optionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: optionsResult.error });\n return err(optionsResult.error);\n }\n\n // 3. Invoke browser\n const credential = (await invoke(optionsResult.value)) as PublicKeyCredential;\n if (!credential) {\n const error = createInvalidArgumentError(\n 'credential',\n `${operation === 'register' ? 'creation' : 'retrieval'} failed`\n );\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Completar en servidor (success lo emite el caller con token/user; 03-eventos-seguridad)\n const finishResult = await finish(startResult.value, credential);\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n return ok(finishResult.value);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n","import { createInvalidArgumentError, validateBase64Url, mapWebAuthnError } from '../errors';\nimport { base64UrlDecodeToArrayBuffer } from '../utils/base64url';\nimport type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n RegisterStartResponse,\n AuthStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Creates credential creation options for WebAuthn.\n * Converts server response to WebAuthn API format.\n * WebAuthn protocol: challenge and rp.id are taken from the server only; do not override.\n * Exported for use by OnboardingManager (same-device) and CrossDeviceManager (QR registration).\n *\n * @param serverChallengePayload - Value of the `.challenge` property from RegisterStartResponse\n * (the nested object with challenge, user, rp, pubKeyCredParams, etc.). Not the full API response.\n */\nexport function createRegistrationOptions(\n serverChallengePayload: RegisterStartResponse['challenge'],\n authenticatorType?: 'platform' | 'cross-platform'\n): Result<CredentialCreationOptions, TryMellonError> {\n try {\n validateBase64Url(serverChallengePayload.challenge, 'challenge');\n validateBase64Url(serverChallengePayload.user.id, 'user.id');\n\n const challengeBuffer = base64UrlDecodeToArrayBuffer(serverChallengePayload.challenge);\n const userIdBuffer = base64UrlDecodeToArrayBuffer(serverChallengePayload.user.id);\n\n // Construir authenticatorSelection: priorizar servidor, permitir override de authenticatorType\n let authenticatorSelection: AuthenticatorSelectionCriteria = {\n userVerification: 'preferred',\n };\n\n if (serverChallengePayload.authenticatorSelection) {\n // Usar valores del servidor como base\n authenticatorSelection = {\n ...serverChallengePayload.authenticatorSelection,\n };\n }\n\n // Si el usuario especifica authenticatorType, sobrescribir authenticatorAttachment\n if (authenticatorType) {\n authenticatorSelection = {\n ...authenticatorSelection,\n authenticatorAttachment: authenticatorType,\n };\n }\n\n const publicKey: PublicKeyCredentialCreationOptions = {\n rp: {\n id: serverChallengePayload.rp.id,\n name: serverChallengePayload.rp.name,\n },\n user: {\n id: userIdBuffer,\n name: serverChallengePayload.user.name,\n displayName: serverChallengePayload.user.displayName,\n },\n challenge: challengeBuffer,\n pubKeyCredParams: serverChallengePayload.pubKeyCredParams,\n ...(serverChallengePayload.timeout !== undefined && {\n timeout: serverChallengePayload.timeout,\n }),\n attestation: 'none',\n authenticatorSelection,\n ...(serverChallengePayload.excludeCredentials && {\n excludeCredentials: serverChallengePayload.excludeCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n };\n\n return ok({ publicKey });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Creates authentication options for WebAuthn.\n * Converts server response to WebAuthn API format.\n * WebAuthn protocol: challenge and rpId are taken from the server only; do not override.\n */\nexport function createAuthenticationOptions(\n challenge: AuthStartResponse['challenge'],\n mediation?: AuthenticateOptions['mediation']\n): Result<CredentialRequestOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n\n return ok({\n publicKey: {\n challenge: challengeBuffer,\n rpId: challenge.rpId,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n userVerification: challenge.userVerification ?? 'preferred',\n ...(challenge.allowCredentials && {\n allowCredentials: challenge.allowCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n },\n ...(mediation !== undefined && { mediation }),\n });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Registers a new passkey for a user.\n * Handles the full WebAuthn registration flow.\n */\nexport async function registerPasskey(\n options: RegisterOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RegisterResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const result = await invokeCeremony<\n RegisterStartResponse,\n RegisterResult,\n CredentialCreationOptions\n >({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.startRegister({ external_user_id: extId }),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge, options.authenticatorType),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.create(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishRegister({\n session_id: startResult.session_id,\n credential: serializeCredentialForRegister(credential),\n ...(options.successUrl && { success_url: options.successUrl }),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n success: true,\n credentialId: finishResult.value.credential_id,\n credential_id: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n ...(finishResult.value.redirect_url && { redirectUrl: finishResult.value.redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n\n/**\n * Authenticates a user with their passkey.\n * Handles the full WebAuthn authentication flow.\n */\nexport async function authenticatePasskey(\n options: AuthenticateOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<AuthenticateResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n const hasUserId = extId !== undefined && typeof extId === 'string' && extId.trim() !== '';\n\n const result = await invokeCeremony<\n AuthStartResponse,\n AuthenticateResult,\n CredentialRequestOptions\n >({\n operation: 'authenticate',\n eventEmitter,\n start: () =>\n apiClient.startAuth(hasUserId ? { external_user_id: (extId as string).trim() } : {}),\n createOptions: (startResult) =>\n createAuthenticationOptions(startResult.challenge, options.mediation),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.get(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishAuthentication({\n session_id: startResult.session_id,\n credential: serializeCredentialForAuth(credential),\n ...(options.successUrl && { success_url: options.successUrl }),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n authenticated: finishResult.value.authenticated,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n signals: finishResult.value.signals,\n ...(finishResult.value.redirect_url && { redirectUrl: finishResult.value.redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'authenticate',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n","export async function waitWithAbort(\n intervalMs: number,\n signal?: AbortSignal\n): Promise<'aborted' | 'completed'> {\n // Fast path when no signal is provided: simple sleep.\n if (!signal) {\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n return 'completed';\n }\n\n if (signal.aborted) {\n return 'aborted';\n }\n\n return new Promise<'aborted' | 'completed'>((resolve) => {\n const onAbort = () => {\n cleanup();\n resolve('aborted');\n };\n\n const cleanup = () => {\n clearTimeout(timeout);\n signal.removeEventListener('abort', onAbort);\n };\n\n const timeout = setTimeout(() => {\n cleanup();\n resolve('completed');\n }, intervalMs);\n\n signal.addEventListener('abort', onAbort);\n });\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type { OnboardingStartOptions, OnboardingCompleteResult } from '../types';\nimport { createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\nimport { waitWithAbort } from './polling-utils';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class OnboardingManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Executes the full onboarding flow in a single call.\n * 1. Starts onboarding\n * 2. Polls for 'pending_passkey' or 'completed' status\n * 3. If pending_passkey: when API returns challenge, registers passkey (WebAuthn) then completes onboarding\n * 4. If pending_passkey but API does not return challenge: returns NOT_SUPPORTED with onboarding_url for user to complete elsewhere\n */\n async startFlow(\n options: OnboardingStartOptions & { company_name?: string },\n signal?: AbortSignal\n ): Promise<Result<OnboardingCompleteResult, TryMellonError>> {\n const startResult = await this.apiClient.startOnboarding({ user_role: options.user_role });\n if (!startResult.ok) return err(startResult.error);\n\n const { session_id } = startResult.value;\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const waitResult = await waitWithAbort(POLL_INTERVAL_MS, signal);\n if (waitResult === 'aborted') {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const statusResult = await this.apiClient.getOnboardingStatus(session_id);\n if (!statusResult.ok) return err(statusResult.error);\n\n const status = statusResult.value.status;\n const onboarding_url = statusResult.value.onboarding_url;\n\n if (status === 'pending_passkey') {\n const registerInfoResult = await this.apiClient.getOnboardingRegister(session_id);\n if (!registerInfoResult.ok) return err(registerInfoResult.error);\n\n const registerInfo = registerInfoResult.value as OnboardingRegisterResponseWithChallenge;\n\n if (!registerInfo.challenge) {\n return err(\n createError(\n 'NOT_SUPPORTED',\n 'Onboarding requires user action - complete passkey registration at the provided onboarding_url',\n { onboarding_url }\n )\n );\n }\n\n const creationOptionsResult = createRegistrationOptions(registerInfo.challenge);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n const registerPasskeyResult = await this.apiClient.registerOnboardingPasskey(session_id, {\n credential: serializedCredential,\n challenge: registerInfo.challenge.challenge,\n });\n if (!registerPasskeyResult.ok) return err(registerPasskeyResult.error);\n\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n\n if (status === 'completed') {\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n }\n\n return err(createError('TIMEOUT', 'Onboarding timed out'));\n }\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceContextAuth,\n CrossDeviceContextRegistration,\n} from '../types';\nimport { createAuthenticationOptions, createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport { waitWithAbort } from './polling-utils';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class CrossDeviceManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Initializes a cross-device authentication session.\n * Typically called by the desktop side to get a QR code URL.\n */\n async init(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceAuth();\n }\n\n /**\n * Initializes a cross-device registration session (create account via QR).\n * Typically called by the desktop side to get a QR code URL for new users.\n * Pass externalUserId for known users; omit for anonymous registration.\n */\n async initRegistration(options?: {\n externalUserId?: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceRegistration(options);\n }\n\n /**\n * High-level helper to poll for session status until it is completed.\n * Typically called by the desktop side after showing the QR code.\n * Pass pollingToken from init() result so the backend can verify the poller is the initiator.\n */\n async waitForSession(\n sessionId: string,\n signal?: AbortSignal,\n pollingToken?: string | null\n ): Promise<\n Result<{ session_token: string; user_id: string; redirectUrl?: string }, TryMellonError>\n > {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n const statusResult = await this.apiClient.getCrossDeviceStatus(sessionId, pollingToken);\n if (!statusResult.ok) return err(statusResult.error);\n\n if (statusResult.value.status === 'completed') {\n if (!statusResult.value.session_token || !statusResult.value.user_id) {\n return err(createError('UNKNOWN_ERROR', 'Missing data in completed session'));\n }\n const redirectUrl =\n statusResult.value.redirect_url != null && statusResult.value.redirect_url !== ''\n ? statusResult.value.redirect_url\n : undefined;\n return ok({\n session_token: statusResult.value.session_token,\n user_id: statusResult.value.user_id,\n ...(redirectUrl !== undefined && { redirectUrl }),\n });\n }\n\n const waitResult = await waitWithAbort(POLL_INTERVAL_MS, signal);\n if (waitResult === 'aborted') {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n }\n\n return err(createError('TIMEOUT', 'Cross-device authentication timed out'));\n }\n\n /**\n * Approves a cross-device session.\n * Typically called by the mobile side after scanning a QR code.\n * Branches by context type: registration → credentials.create + verify-registration;\n * auth → credentials.get + verify.\n */\n async approve(sessionId: string): Promise<Result<void, TryMellonError>> {\n const contextResult = await this.apiClient.getCrossDeviceContext(sessionId);\n if (!contextResult.ok) return err(contextResult.error);\n\n const context = contextResult.value;\n\n if (context.type === 'registration') {\n return this.executeRegistrationApproval(sessionId, context);\n }\n return this.executeAuthApproval(sessionId, context);\n }\n\n /**\n * Executes the registration branch: create credential and verify-registration.\n */\n private async executeRegistrationApproval(\n sessionId: string,\n context: CrossDeviceContextRegistration\n ): Promise<Result<void, TryMellonError>> {\n const creationOptionsResult = createRegistrationOptions(context.options);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceRegistration({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n\n /**\n * Executes the auth branch: get credential and verify.\n */\n private async executeAuthApproval(\n sessionId: string,\n context: CrossDeviceContextAuth\n ): Promise<Result<void, TryMellonError>> {\n const requestOptionsResult = createAuthenticationOptions(context.options);\n if (!requestOptionsResult.ok) return err(requestOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.get(requestOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'get');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForAuth(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceAuth({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n}\n","import type { EventHandler, EventPayload, TryMellonEvent } from '../types';\n\nexport class EventEmitter {\n private handlers: Map<TryMellonEvent, Set<EventHandler>>;\n\n constructor() {\n this.handlers = new Map();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n let handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n handlersSet = new Set();\n this.handlers.set(event, handlersSet);\n }\n\n handlersSet.add(handler);\n\n return () => {\n this.off(event, handler);\n };\n }\n\n off(event: TryMellonEvent, handler: EventHandler): void {\n const handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n return;\n }\n handlersSet.delete(handler);\n if (handlersSet.size === 0) {\n this.handlers.delete(event);\n }\n }\n\n emit(event: TryMellonEvent, payload: EventPayload): void {\n const handlersSet = this.handlers.get(event);\n if (handlersSet) {\n for (const handler of handlersSet) {\n try {\n handler(payload);\n } catch {\n // Silently ignore handler errors to prevent one handler from breaking others\n // Handler errors are the responsibility of the handler implementation\n }\n }\n }\n }\n\n removeAllListeners(): void {\n this.handlers.clear();\n }\n}\n","export const COSE_ALGORITHM_ES256 = -7;\nexport const COSE_ALGORITHM_RS256 = -257;\n\nexport const DEFAULT_API_BASE_URL = 'https://api.trymellonauth.com';\nexport const DEFAULT_TELEMETRY_ENDPOINT = 'https://api.trymellonauth.com/v1/telemetry';\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\nexport const MIN_TIMEOUT_MS = 1000;\nexport const MAX_TIMEOUT_MS = 300000;\nexport const MIN_MAX_RETRIES = 0;\nexport const MAX_MAX_RETRIES = 10;\nexport const MIN_RETRY_DELAY_MS = 100;\nexport const MAX_RETRY_DELAY_MS = 10000;\n\n/**\n * Fixed session token returned by register() and authenticate() when sandbox mode is enabled.\n * Backends MUST NOT accept this token in production; only in development for testing the integration flow.\n */\nexport const SANDBOX_SESSION_TOKEN = 'trymellon_sandbox_session_token_v1';\n","import type { TelemetrySender, TelemetryPayload } from '../ports/telemetry';\n\n/**\n * Default telemetry sender: sends payload via sendBeacon (or fetch) to the given endpoint.\n * No retries; fire-and-forget.\n */\nexport function createDefaultTelemetrySender(endpoint: string): TelemetrySender {\n return {\n async send(payload: TelemetryPayload): Promise<void> {\n const body = JSON.stringify(payload);\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n navigator.sendBeacon(endpoint, body);\n return;\n }\n if (typeof fetch !== 'undefined') {\n await fetch(endpoint, {\n method: 'POST',\n body,\n headers: { 'Content-Type': 'application/json' },\n keepalive: true,\n });\n }\n },\n };\n}\n","export type TelemetryEvent = 'register' | 'authenticate';\n\nexport type TelemetryPayload = {\n event: TelemetryEvent;\n latencyMs: number;\n ok: true;\n};\n\nexport interface TelemetrySender {\n send(payload: TelemetryPayload): Promise<void>;\n}\n\n/**\n * Builds the minimal telemetry payload (no PII).\n */\nexport function buildTelemetryPayload(event: TelemetryEvent, latencyMs: number): TelemetryPayload {\n return { event, latencyMs, ok: true };\n}\n","import type { ApiClient } from '../api';\nimport type { EventEmitter } from '../events';\nimport type {\n AuthenticateOptions,\n AuthenticateResult,\n RegisterOptions,\n RegisterResult,\n} from '../../types';\nimport type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { buildTelemetryPayload, type TelemetrySender } from '../ports/telemetry';\nimport { registerPasskey, authenticatePasskey } from '../webauthn';\n\ntype AuthOperation = 'register' | 'authenticate';\n\ntype AuthOptions = RegisterOptions | AuthenticateOptions;\n\nexport class AuthService {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly eventEmitter: EventEmitter,\n private readonly sandbox: boolean,\n private readonly sandboxToken: string,\n private readonly telemetrySender?: TelemetrySender\n ) {}\n\n private async sandboxAuthResult(\n operation: AuthOperation,\n options: AuthOptions\n ): Promise<Result<RegisterResult | AuthenticateResult, TryMellonError>> {\n const externalUserId =\n 'externalUserId' in options\n ? (options.externalUserId ?? options.external_user_id ?? 'sandbox')\n : (options.external_user_id ?? options.externalUserId ?? 'sandbox');\n const externalId = typeof externalUserId === 'string' ? externalUserId : 'sandbox';\n\n if (operation === 'register') {\n return Promise.resolve(\n ok({\n success: true,\n credentialId: '',\n status: 'sandbox',\n sessionToken: this.sandboxToken,\n user: { userId: 'sandbox-user', externalUserId: externalId },\n })\n );\n }\n\n return Promise.resolve(\n ok({\n authenticated: true,\n sessionToken: this.sandboxToken,\n user: { userId: 'sandbox-user', externalUserId: externalId },\n })\n );\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n if (this.sandbox) {\n const result = await this.sandboxAuthResult('register', options);\n if (result.ok) {\n this.eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result as Result<RegisterResult, TryMellonError>;\n }\n\n const start = Date.now();\n const result = await registerPasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('register', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n if (this.sandbox) {\n const result = await this.sandboxAuthResult('authenticate', options);\n if (result.ok) {\n this.eventEmitter.emit('success', {\n type: 'success',\n operation: 'authenticate',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result as Result<AuthenticateResult, TryMellonError>;\n }\n\n const start = Date.now();\n const result = await authenticatePasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('authenticate', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n}\n","import type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RecoverAccountOptions,\n RecoverAccountResult,\n RecoveryVerifyResponse,\n RegisterStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { createInvalidArgumentError } from '../errors';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { createRegistrationOptions } from './webauthn';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Recovers an account using an email OTP and creates a new passkey credential.\n * Manages the complete orchestrated WebAuthn registration flow for recovery.\n */\nexport async function recoverAccount(\n options: RecoverAccountOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RecoverAccountResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n if (!options.otp || typeof options.otp !== 'string' || options.otp.trim().length !== 6) {\n const error = createInvalidArgumentError('otp', 'must be a 6-digit string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const result = await invokeCeremony<\n RecoveryVerifyResponse,\n RecoverAccountResult,\n CredentialCreationOptions\n >({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.verifyAccountRecoveryOtp(extId, options.otp),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge as RegisterStartResponse['challenge']),\n invoke: async (ceremonyOptions) => navigator.credentials.create(ceremonyOptions),\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.completeAccountRecovery(\n startResult.recovery_session_id,\n serializeCredentialForRegister(credential)\n );\n\n if (!finishResult.ok) return err(finishResult.error);\n\n const {\n credential_id,\n status,\n session_token,\n user: userPayload,\n redirect_url,\n } = finishResult.value;\n return ok({\n success: true,\n credentialId: credential_id,\n status,\n sessionToken: session_token,\n user: {\n userId: userPayload.user_id,\n externalUserId: userPayload.external_user_id,\n email: userPayload.email,\n metadata: userPayload.metadata,\n },\n ...(redirect_url !== undefined && { redirectUrl: redirect_url }),\n });\n },\n });\n\n if (result.ok) {\n eventEmitter.emit('success', {\n type: 'success',\n operation: 'register',\n token: result.value.sessionToken,\n user: result.value.user,\n });\n }\n return result;\n}\n","import type { ApiClient } from '../api';\nimport type { EventEmitter } from '../events';\nimport type { RecoverAccountOptions, RecoverAccountResult } from '../../types';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { recoverAccount } from '../recover';\n\nexport class RecoveryService {\n constructor(\n private readonly apiClient: ApiClient,\n private readonly eventEmitter: EventEmitter\n ) {}\n\n recover(options: RecoverAccountOptions): Promise<Result<RecoverAccountResult, TryMellonError>> {\n return recoverAccount(options, this.apiClient, this.eventEmitter);\n }\n}\n","import { ApiClient } from './api';\nimport { FetchHttpClient } from './fetch-client';\nimport { OnboardingManager } from './onboarding-manager';\nimport { CrossDeviceManager } from './cross-device-manager';\nimport { EventEmitter } from './events';\nimport { isWebAuthnSupported, getClientStatus } from '../utils/support';\nimport { validateUrl, validateRange, createInvalidArgumentError } from '../errors';\nimport {\n DEFAULT_API_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_RETRY_DELAY_MS,\n DEFAULT_TELEMETRY_ENDPOINT,\n MIN_TIMEOUT_MS,\n MAX_TIMEOUT_MS,\n MIN_MAX_RETRIES,\n MAX_MAX_RETRIES,\n MIN_RETRY_DELAY_MS,\n MAX_RETRY_DELAY_MS,\n SANDBOX_SESSION_TOKEN,\n} from './constants';\nimport { createDefaultTelemetrySender } from './adapters/telemetry-sender';\nimport type { TelemetrySender } from './ports/telemetry';\nimport type {\n TryMellonConfig,\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n ClientStatus,\n TryMellonEvent,\n EventHandler,\n EmailFallbackStartOptions,\n EmailFallbackVerifyOptions,\n EmailFallbackVerifyResult,\n SessionValidateResponse,\n RecoverAccountOptions,\n} from '../types';\nimport { ok, err, type Result } from '../utils/result';\nimport { type TryMellonError, isTryMellonError } from '../errors';\nimport { AuthService } from './services/auth-service';\nimport { RecoveryService } from './services/recovery-service';\n\ndeclare const __VERSION__: string;\n\nexport class TryMellon {\n private readonly sandbox: boolean;\n private readonly sandboxToken: string;\n private apiClient: ApiClient;\n private eventEmitter: EventEmitter;\n private telemetrySender: TelemetrySender | undefined;\n private crossDeviceManager: CrossDeviceManager;\n private authService: AuthService;\n private recoveryService: RecoveryService;\n public onboarding: OnboardingManager;\n\n /**\n * Creates a new TryMellon instance.\n * Validates config and returns a Result.\n * @param config SDK configuration\n */\n static create(config: TryMellonConfig): Result<TryMellon, TryMellonError> {\n try {\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n return err(createInvalidArgumentError('appId', 'must be a non-empty string'));\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n return err(createInvalidArgumentError('publishableKey', 'must be a non-empty string'));\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n // Safe to instantiate now\n return ok(new TryMellon(config));\n } catch (e) {\n if (isTryMellonError(e)) {\n return err(e);\n }\n return err(createInvalidArgumentError('config', (e as Error).message));\n }\n }\n\n /**\n * @deprecated Use `TryMellon.create(config)` instead to handle validation errors safely.\n * This constructor will throw errors if configuration is invalid.\n */\n constructor(config: TryMellonConfig) {\n this.sandbox = config.sandbox === true;\n this.sandboxToken =\n this.sandbox && config.sandboxToken != null && config.sandboxToken !== ''\n ? config.sandboxToken\n : SANDBOX_SESSION_TOKEN;\n\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n // Legacy validation for direct constructor usage (still throws to maintain behavior for legacy code,\n // but create() handles this safely before calling constructor)\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n throw createInvalidArgumentError('appId', 'must be a non-empty string');\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n throw createInvalidArgumentError('publishableKey', 'must be a non-empty string');\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n // validateUrl throws, which is expected for the constructor. create() catches it.\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const httpClient = new FetchHttpClient(timeoutMs, maxRetries, retryDelayMs, config.logger);\n\n const originHeader =\n config.origin ??\n (typeof window !== 'undefined' && window?.location?.origin\n ? window.location.origin\n : undefined);\n\n const defaultHeaders: Record<string, string> = {\n 'X-App-Id': appId.trim(),\n Authorization: `Bearer ${publishableKey.trim()}`,\n ...(originHeader && { Origin: originHeader }),\n };\n\n this.apiClient = new ApiClient(httpClient, apiBaseUrl, defaultHeaders);\n this.eventEmitter = new EventEmitter();\n\n if (config.enableTelemetry) {\n this.telemetrySender =\n config.telemetrySender ??\n createDefaultTelemetrySender(config.telemetryEndpoint ?? DEFAULT_TELEMETRY_ENDPOINT);\n }\n\n this.authService = new AuthService(\n this.apiClient,\n this.eventEmitter,\n this.sandbox,\n this.sandboxToken,\n this.telemetrySender\n );\n this.recoveryService = new RecoveryService(this.apiClient, this.eventEmitter);\n this.onboarding = new OnboardingManager(this.apiClient);\n this.crossDeviceManager = new CrossDeviceManager(this.apiClient);\n }\n\n static isSupported(): boolean {\n return isWebAuthnSupported();\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n return this.authService.register(options);\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n return this.authService.authenticate(options);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n if (this.sandbox && sessionToken === this.sandboxToken) {\n return Promise.resolve(\n ok({\n valid: true,\n user_id: 'sandbox-user',\n external_user_id: 'sandbox',\n tenant_id: 'sandbox-tenant',\n app_id: 'sandbox-app',\n })\n );\n }\n return this.apiClient.validateSession(sessionToken);\n }\n\n async getStatus(): Promise<ClientStatus> {\n return getClientStatus();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n return this.eventEmitter.on(event, handler);\n }\n\n version(): string {\n return typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0';\n }\n\n fallback = {\n email: {\n start: async (options: EmailFallbackStartOptions): Promise<Result<void, TryMellonError>> => {\n return this.apiClient.startEmailFallback(options);\n },\n verify: async (\n options: EmailFallbackVerifyOptions\n ): Promise<Result<EmailFallbackVerifyResult, TryMellonError>> => {\n const result = await this.apiClient.verifyEmailCode({\n userId: options.userId,\n code: options.code,\n ...(options.successUrl && { successUrl: options.successUrl }),\n });\n if (!result.ok) return result;\n return ok({\n sessionToken: result.value.sessionToken,\n ...(result.value.redirectUrl && { redirectUrl: result.value.redirectUrl }),\n });\n },\n },\n };\n\n auth = {\n crossDevice: {\n init: () => this.crossDeviceManager.init(),\n initRegistration: (options?: { externalUserId?: string }) =>\n this.crossDeviceManager.initRegistration(options ?? {}),\n waitForSession: (sessionId: string, signal?: AbortSignal, pollingToken?: string | null) =>\n this.crossDeviceManager.waitForSession(sessionId, signal, pollingToken),\n getContext: (sessionId: string) => this.apiClient.getCrossDeviceContext(sessionId),\n approve: (sessionId: string) => this.crossDeviceManager.approve(sessionId),\n },\n recoverAccount: (options: RecoverAccountOptions) => this.recoveryService.recover(options),\n };\n}\n"],"mappings":"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","names":["angular_exports","__export","TRYMELLON_CONFIG","TryMellonService","provideTryMellonConfig","__toCommonJS","import_core","ok","value","err","error","TryMellonError","_TryMellonError","code","message","details","DEFAULT_MESSAGES","createError","isTryMellonError","error","createNotSupportedError","createInvalidArgumentError","field","reason","createError","createCredentialError","operation","createEncodingError","type","validateUrl","url","fieldName","urlObj","createInvalidArgumentError","error","isTryMellonError","validateRange","value","min","max","validateBase64Url","s","DOM_EXCEPTION_ERROR_MAP","mapBackendErrorCodeToTryMellon","backendCode","normalized","mapWebAuthnError","name","message","errorCode","createError","isObject","value","isString","isNumber","isBoolean","isArray","validationError","message","details","err","createError","required","obj","key","validateChallengeRP","rp","data","isObject","isString","validationError","ok","validateChallengeUser","user","validatePubKeyCredParams","params","isArray","item","isNumber","validateUserEntity","userId","required","externalUserId","email","metadata","validateRegisterStartResponse","data","isObject","validationError","session_id","required","isString","challenge","rpResult","validateChallengeRP","userResult","validateChallengeUser","challengeStr","pubKeyCredParamsResult","validatePubKeyCredParams","timeout","isNumber","excludeCredentials","isArray","c","authenticatorSelection","ok","validateAuthStartResponse","ch","rpId","allowCredentials","userVerification","validateRegisterFinishResponse","credential_id","status","session_token","user","validateUserEntity","redirect_url","validateAuthFinishResponse","authenticated","signals","isBoolean","validateSessionValidateResponse","data","isObject","validationError","valid","required","user_id","external_user_id","tenant_id","app_id","isBoolean","isString","ok","validateEmailVerifyResponse","data","isObject","validationError","raw","isString","redirect_url","ok","ONBOARDING_STATUSES","REGISTER_PASSKEY_STATUSES","validateOnboardingStartResponse","data","isObject","validationError","session_id","required","onboarding_url","expires_in","isString","isNumber","ok","validateOnboardingStatusResponse","status","validateOnboardingRegisterResponse","challenge","parsedChallenge","chResult","validateOnboardingChallenge","rp","user","challengeStr","pubKeyCredParams","isArray","item","validateOnboardingRegisterPasskeyResponse","user_id","tenant_id","validateOnboardingCompleteResponse","session_token","validateCrossDeviceVerifyResponse","data","ok","isObject","validationError","isCreationOptionsShape","opts","o","isRequestOptionsShape","validateCrossDeviceInitResponse","payload","session_id","qr_url","expires_at","polling_token","isString","result","validateCrossDeviceStatusResponse","status","user_id","session_token","redirect_url","validateCrossDeviceContextResponse","rawType","type","options","MAX_CONTEXT_LENGTH","approval_context","optionalContextString","application_name","extra","value","maxLength","validateRecoveryVerifyResponse","data","isObject","validationError","challenge","required","recovery_session_id","isString","ok","validateRecoveryCompleteResponse","status","session_token","user","credential_id","user_id","redirect_url","userObj","ApiClient","httpClient","baseUrl","defaultHeaders","extra","path","body","validate","url","result","err","headers","request","validateRegisterStartResponse","validateAuthStartResponse","validateRegisterFinishResponse","validateAuthFinishResponse","sessionToken","validateSessionValidateResponse","options","ok","validateEmailVerifyResponse","validateOnboardingStartResponse","sessionId","validateOnboardingStatusResponse","validateOnboardingRegisterResponse","validateOnboardingRegisterPasskeyResponse","validateOnboardingCompleteResponse","validateCrossDeviceInitResponse","trimmed","pollingToken","validateCrossDeviceStatusResponse","validateCrossDeviceContextResponse","validateCrossDeviceVerifyResponse","externalUserId","otp","validateRecoveryVerifyResponse","recoverySessionId","credential","validateRecoveryCompleteResponse","isEnvelopeSuccess","data","isEnvelopeError","o","err","parseHttpErrorBody","errorData","statusText","mapBackendErrorCodeToTryMellon","body","errObj","message","rawCode","code","RETRY_DELAY_CAP_MS","generateRequestId","getRetryDelayMs","attempt","baseMs","delay","shouldRetryOnStatus","method","status","FetchHttpClient","timeoutMs","maxRetries","retryDelayMs","logger","url","headers","config","requestId","lastError","controller","timeoutId","response","errResult","createError","resolve","ok","raw","error","base64UrlEncode","buf","bytes","binary","b","createEncodingError","base64UrlDecode","s","base64","padding","padded","c","base64UrlDecodeToArrayBuffer","buffer","isValidCredentialResponse","response","serializeCredentialForRegister","credential","createError","clientDataJSON","attestationObject","base64UrlEncode","serializeCredentialForAuth","authenticatorData","signature","userHandle","isWebAuthnSupported","isPlatformAuthenticatorAvailable","getClientStatus","isPasskeySupported","platformAuthenticatorAvailable","validateCredentialStructure","credential","operation","createCredentialError","invokeCeremony","context","operation","eventEmitter","start","createOptions","invoke","finish","isWebAuthnSupported","error","createNotSupportedError","err","startResult","optionsResult","credential","createInvalidArgumentError","validateCredentialStructure","e","mapWebAuthnError","finishResult","ok","tryMellonError","createRegistrationOptions","serverChallengePayload","authenticatorType","validateBase64Url","challengeBuffer","base64UrlDecodeToArrayBuffer","userIdBuffer","authenticatorSelection","publicKey","cred","ok","e","err","mapWebAuthnError","createAuthenticationOptions","challenge","mediation","registerPasskey","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","result","invokeCeremony","startResult","ceremonyOptions","opts","credential","finishResult","serializeCredentialForRegister","authenticatePasskey","hasUserId","serializeCredentialForAuth","waitWithAbort","intervalMs","signal","resolve","onAbort","cleanup","timeout","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","OnboardingManager","apiClient","options","signal","startResult","err","session_id","attempt","createError","waitWithAbort","statusResult","status","onboarding_url","registerInfoResult","registerInfo","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","registerPasskeyResult","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","CrossDeviceManager","apiClient","options","sessionId","signal","pollingToken","err","createError","attempt","statusResult","redirectUrl","ok","waitWithAbort","contextResult","context","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","requestOptionsResult","createAuthenticationOptions","serializeCredentialForAuth","EventEmitter","event","handler","handlersSet","payload","DEFAULT_API_BASE_URL","DEFAULT_TELEMETRY_ENDPOINT","SANDBOX_SESSION_TOKEN","createDefaultTelemetrySender","endpoint","payload","body","buildTelemetryPayload","event","latencyMs","AuthService","apiClient","eventEmitter","sandbox","sandboxToken","telemetrySender","operation","options","externalUserId","externalId","ok","result","start","registerPasskey","buildTelemetryPayload","authenticatePasskey","recoverAccount","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","err","result","invokeCeremony","startResult","createRegistrationOptions","ceremonyOptions","credential","finishResult","serializeCredentialForRegister","credential_id","status","session_token","userPayload","redirect_url","ok","RecoveryService","apiClient","eventEmitter","options","recoverAccount","TryMellon","_TryMellon","config","appId","publishableKey","err","createInvalidArgumentError","apiBaseUrl","DEFAULT_API_BASE_URL","validateUrl","timeoutMs","validateRange","ok","e","isTryMellonError","SANDBOX_SESSION_TOKEN","maxRetries","retryDelayMs","httpClient","FetchHttpClient","originHeader","defaultHeaders","ApiClient","EventEmitter","createDefaultTelemetrySender","DEFAULT_TELEMETRY_ENDPOINT","AuthService","RecoveryService","OnboardingManager","CrossDeviceManager","isWebAuthnSupported","options","sessionToken","getClientStatus","event","handler","result","sessionId","signal","pollingToken","TRYMELLON_CONFIG","_TryMellonService_decorators","_init","TryMellonService","TryMellon","__decoratorStart","__decorateElement","__runInitializers","provideTryMellonConfig","config","TRYMELLON_CONFIG"]}
1
+ {"version":3,"sources":["../src/angular/index.ts","../src/angular/trymellon.service.ts"],"sourcesContent":["import type { Provider } from '@angular/core';\nimport type { TryMellon } from '../core/trymellon';\nimport { TRYMELLON_CLIENT } from './trymellon.service';\n\nexport { TryMellonService, TRYMELLON_CLIENT } from './trymellon.service';\n\nexport function provideTryMellon(client: TryMellon): Provider {\n return { provide: TRYMELLON_CLIENT, useValue: client } as Provider;\n}\n","import { Injectable, InjectionToken, inject } from '@angular/core';\nimport type { TryMellon } from '../core/trymellon';\n\nexport const TRYMELLON_CLIENT = new InjectionToken<TryMellon>('TRYMELLON_CLIENT');\n\n@Injectable({ providedIn: 'root' })\nexport class TryMellonService {\n private readonly _client = inject(TRYMELLON_CLIENT, { optional: true });\n\n get client(): TryMellon {\n if (this._client == null) {\n throw new Error(\n 'TryMellonService: provide TRYMELLON_CLIENT (e.g. via provideTryMellon(client))'\n );\n }\n return this._client;\n }\n\n enroll(options: Parameters<TryMellon['enroll']>[0]): ReturnType<TryMellon['enroll']> {\n return this.client.enroll(options);\n }\n\n getContextHash(): string {\n return this.client.getContextHash();\n }\n}\n"],"mappings":";mrEAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,sBAAAE,EAAA,qBAAAC,EAAA,qBAAAC,IAAA,eAAAC,EAAAL,GCAA,IAAAM,EAAmD,yBAG5C,IAAMC,EAAmB,IAAI,iBAA0B,kBAAkB,EAHhFC,EAAAC,EAKAD,EAAA,IAAC,cAAW,CAAE,WAAY,MAAO,CAAC,GAC3B,IAAME,EAAN,KAAuB,CACX,WAAU,UAAOH,EAAkB,CAAE,SAAU,EAAK,CAAC,EAEtE,IAAI,QAAoB,CACtB,GAAI,KAAK,SAAW,KAClB,MAAM,IAAI,MACR,gFACF,EAEF,OAAO,KAAK,OACd,CAEA,OAAOI,EAA8E,CACnF,OAAO,KAAK,OAAO,OAAOA,CAAO,CACnC,CAEA,gBAAyB,CACvB,OAAO,KAAK,OAAO,eAAe,CACpC,CACF,EAnBOF,EAAAG,EAAA,MAAMF,EAANG,EAAAJ,EAAA,qBADPD,EACaE,GAANI,EAAAL,EAAA,EAAMC,GDAN,SAASK,EAAiBC,EAA6B,CAC5D,MAAO,CAAE,QAASC,EAAkB,SAAUD,CAAO,CACvD","names":["angular_exports","__export","TRYMELLON_CLIENT","TryMellonService","provideTryMellon","__toCommonJS","import_core","TRYMELLON_CLIENT","_TryMellonService_decorators","_init","TryMellonService","options","__decoratorStart","__decorateElement","__runInitializers","provideTryMellon","client","TRYMELLON_CLIENT"]}
@@ -1,13 +1,14 @@
1
1
  import { InjectionToken, Provider } from '@angular/core';
2
- import { T as TryMellon, e as TryMellonConfig } from './trymellon-P7BPxIry.cjs';
2
+ import { T as TryMellon } from './trymellon-CO_2wLZz.cjs';
3
3
 
4
- declare const TRYMELLON_CONFIG: InjectionToken<TryMellonConfig>;
4
+ declare const TRYMELLON_CLIENT: InjectionToken<TryMellon>;
5
5
  declare class TryMellonService {
6
- private readonly config;
7
- private _client;
6
+ private readonly _client;
8
7
  get client(): TryMellon;
8
+ enroll(options: Parameters<TryMellon['enroll']>[0]): ReturnType<TryMellon['enroll']>;
9
+ getContextHash(): string;
9
10
  }
10
11
 
11
- declare function provideTryMellonConfig(config: TryMellonConfig): Provider;
12
+ declare function provideTryMellon(client: TryMellon): Provider;
12
13
 
13
- export { TRYMELLON_CONFIG, TryMellonService, provideTryMellonConfig };
14
+ export { TRYMELLON_CLIENT, TryMellonService, provideTryMellon };
package/dist/angular.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import { InjectionToken, Provider } from '@angular/core';
2
- import { T as TryMellon, e as TryMellonConfig } from './trymellon-P7BPxIry.js';
2
+ import { T as TryMellon } from './trymellon-CO_2wLZz.js';
3
3
 
4
- declare const TRYMELLON_CONFIG: InjectionToken<TryMellonConfig>;
4
+ declare const TRYMELLON_CLIENT: InjectionToken<TryMellon>;
5
5
  declare class TryMellonService {
6
- private readonly config;
7
- private _client;
6
+ private readonly _client;
8
7
  get client(): TryMellon;
8
+ enroll(options: Parameters<TryMellon['enroll']>[0]): ReturnType<TryMellon['enroll']>;
9
+ getContextHash(): string;
9
10
  }
10
11
 
11
- declare function provideTryMellonConfig(config: TryMellonConfig): Provider;
12
+ declare function provideTryMellon(client: TryMellon): Provider;
12
13
 
13
- export { TRYMELLON_CONFIG, TryMellonService, provideTryMellonConfig };
14
+ export { TRYMELLON_CLIENT, TryMellonService, provideTryMellon };