@trymellon/js 1.2.1 → 1.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/README.MD CHANGED
@@ -1,35 +1,29 @@
1
1
  # @trymellon/js
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/@trymellon/js)](https://www.npmjs.com/package/@trymellon/js)
4
- [![Build Status](https://img.shields.io/github/actions/workflow/status/ResakaGit/trymellon-js/ci.yml)](https://github.com/ResakaGit/trymellon-js/actions)
5
- [![Coverage](https://img.shields.io/codecov/c/github/ResakaGit/trymellon-js)](https://codecov.io/gh/ResakaGit/trymellon-js)
3
+ Official **TryMellon** SDK. Add **Passkeys / WebAuthn** to your app in minutes.
6
4
 
7
- Official **TryMellon** SDK for integrating **passwordless authentication** with **Passkeys / WebAuthn** in web applications.
8
-
9
- This SDK fully abstracts WebAuthn and lets you authenticate users without passwords, returning a result your backend can use to create your own session.
5
+ [![npm version](https://img.shields.io/npm/v/@trymellon/js?style=flat-square)](https://www.npmjs.com/package/@trymellon/js)
6
+ [![Build Status](https://img.shields.io/github/actions/workflow/status/ResakaGit/trymellon-js/ci.yml?style=flat-square)](https://github.com/ResakaGit/trymellon-js/actions)
7
+ [![Coverage](https://img.shields.io/codecov/c/github/ResakaGit/trymellon-js?style=flat-square)](https://codecov.io/gh/ResakaGit/trymellon-js)
8
+ [![Size](https://img.shields.io/bundlephobia/minzip/@trymellon/js?label=minzipped&style=flat-square)](https://bundlephobia.com/package/@trymellon/js)
10
9
 
11
10
  ---
12
11
 
13
- ## What does this SDK do?
14
-
15
- * ✅ Handles the full Passkeys flow in the browser
16
- * ✅ Communicates directly with the TryMellon API
17
- * ✅ Returns a `session_token` your backend can verify
18
- * ✅ Handles Base64URL ↔ ArrayBuffer conversion automatically
19
- * ✅ Event system for better UX (spinners, analytics)
20
- * ✅ Email (OTP) fallback when WebAuthn is not available
21
- * ✅ Automatic retries with exponential backoff
22
- * ✅ Thorough validation of inputs and API responses
12
+ ## Why TryMellon?
23
13
 
24
- ---
14
+ Authentication is hard. WebAuthn (Passkeys) is even harder.
15
+ We built **TryMellon** to solve the complexity without locking you in.
25
16
 
26
- ## What does it NOT do?
17
+ * **Zero Logic:** You don't handle cryptography, public keys, or challenges.
18
+ * **Zero Lock-in:** You own your users. We just verify them.
19
+ * **Zero Friction:** Drop-in SDK that "just works" (Cross-browser handling included).
27
20
 
28
- * Does not create user sessions (your backend does)
29
- * Does not replace your auth system
30
- * Does not store end users
31
- * Does not expose raw WebAuthn APIs
32
- * Does not manage cookies or local storage
21
+ ### What you get:
22
+ * **Passkeys First:** Biometric login (FaceID, TouchID, Windows Hello).
23
+ * **Email Fallback:** Magic OTPs when biometrics aren't available.
24
+ * **Cross-Device Auth:** Login on desktop by scanning a QR with mobile.
25
+ * **Framework Agnostic:** Works with React, Vue, Angular, Svelte, or Vanilla.
26
+ * ✅ **Type-Safe:** First-class TypeScript support (`Result` pattern).
33
27
 
34
28
  ---
35
29
 
@@ -39,6 +33,8 @@ This SDK fully abstracts WebAuthn and lets you authenticate users without passwo
39
33
  npm install @trymellon/js
40
34
  ```
41
35
 
36
+ That's it. No peer dependencies. No bloat.
37
+
42
38
  ---
43
39
 
44
40
  ## Requirements
@@ -190,21 +186,29 @@ npm install @trymellon/js
190
186
  ```typescript
191
187
  import { TryMellon } from '@trymellon/js'
192
188
 
193
- const client = new TryMellon({
189
+ // 1. Initialize safely (Factory Pattern)
190
+ const clientResult = TryMellon.create({
194
191
  appId: 'app_live_xxxx', // From your TryMellon dashboard
195
192
  publishableKey: 'key_live_xxxx', // Application API key
196
193
  })
197
194
 
198
- // Register passkey (camelCase recommended in options)
195
+ if (!clientResult.ok) {
196
+ console.error('Invalid config:', clientResult.error.message);
197
+ throw clientResult.error;
198
+ }
199
+
200
+ const client = clientResult.value;
201
+
202
+ // 2. Register passkey (camelCase recommended in options)
199
203
  const registerResult = await client.register({ externalUserId: 'user_123' })
200
204
  if (registerResult.ok) {
201
- console.log('Session token:', registerResult.value.session_token)
205
+ console.log('Session token:', registerResult.value.sessionToken)
202
206
  }
203
207
 
204
- // Authenticate
208
+ // 3. Authenticate
205
209
  const authResult = await client.authenticate({ externalUserId: 'user_123' })
206
210
  if (authResult.ok) {
207
- console.log('Session token:', authResult.value.session_token)
211
+ console.log('Session token:', authResult.value.sessionToken)
208
212
  }
209
213
  ```
210
214
 
@@ -239,6 +243,41 @@ const client = new TryMellon({
239
243
 
240
244
  ---
241
245
 
246
+ ## Sandbox / development mode
247
+
248
+ For local development or testing the integration flow without a real backend or WebAuthn (e.g. no passkey hardware), enable **sandbox mode**. With `sandbox: true`, `register()` and `authenticate()` return immediately with a fixed session token and a demo user—no API or WebAuthn calls.
249
+
250
+ **Configuration:**
251
+
252
+ - `sandbox` (optional): Set to `true` to enable sandbox mode.
253
+ - `sandboxToken` (optional): Custom token to return. If not set, the exported constant `SANDBOX_SESSION_TOKEN` is used.
254
+
255
+ **Exported constant:** Import `SANDBOX_SESSION_TOKEN` from `@trymellon/js` so your backend can recognize the sandbox token in development. **Your backend MUST NOT accept this token in production**—only in development. See [Backend validation](https://trymellon.com/docs/backend-validation) for the hook contract.
256
+
257
+ **Example:**
258
+
259
+ ```typescript
260
+ import { TryMellon, SANDBOX_SESSION_TOKEN } from '@trymellon/js'
261
+
262
+ const client = new TryMellon({
263
+ sandbox: true,
264
+ appId: 'sandbox',
265
+ publishableKey: 'sandbox',
266
+ })
267
+
268
+ const result = await client.authenticate({ externalUserId: 'dev_user_1' })
269
+ if (result.ok) {
270
+ // result.value.sessionToken === SANDBOX_SESSION_TOKEN
271
+ await fetch('/api/login', {
272
+ method: 'POST',
273
+ headers: { 'Content-Type': 'application/json' },
274
+ body: JSON.stringify({ sessionToken: result.value.sessionToken }),
275
+ })
276
+ }
277
+ ```
278
+
279
+ ---
280
+
242
281
  ## Basic usage
243
282
 
244
283
  ### Check WebAuthn support
@@ -268,7 +307,7 @@ await fetch('/api/login', {
268
307
  method: 'POST',
269
308
  headers: { 'Content-Type': 'application/json' },
270
309
  body: JSON.stringify({
271
- sessionToken: result.value.session_token
310
+ sessionToken: result.value.sessionToken
272
311
  })
273
312
  })
274
313
  ```
@@ -284,12 +323,12 @@ await fetch('/api/login', {
284
323
  ```typescript
285
324
  {
286
325
  success: true,
287
- credential_id: string,
326
+ credentialId: string,
288
327
  status: string,
289
- session_token: string,
328
+ sessionToken: string,
290
329
  user: {
291
- user_id: string,
292
- external_user_id: string,
330
+ userId: string,
331
+ externalUserId: string,
293
332
  email?: string,
294
333
  metadata?: Record<string, unknown>
295
334
  }
@@ -309,7 +348,7 @@ await fetch('/api/login', {
309
348
  method: 'POST',
310
349
  headers: { 'Content-Type': 'application/json' },
311
350
  body: JSON.stringify({
312
- sessionToken: result.session_token
351
+ sessionToken: result.value.sessionToken
313
352
  })
314
353
  })
315
354
  ```
@@ -325,10 +364,10 @@ await fetch('/api/login', {
325
364
  ```typescript
326
365
  {
327
366
  authenticated: boolean,
328
- session_token: string,
367
+ sessionToken: string,
329
368
  user: {
330
- user_id: string,
331
- external_user_id: string,
369
+ userId: string,
370
+ externalUserId: string,
332
371
  email?: string,
333
372
  metadata?: Record<string, unknown>
334
373
  },
@@ -433,7 +472,10 @@ When WebAuthn is not available, you can use the email fallback. All methods retu
433
472
 
434
473
  ```typescript
435
474
  // 1. Send OTP code by email
436
- const startResult = await client.fallback.email.start({ userId: 'user_123' })
475
+ const startResult = await client.fallback.email.start({
476
+ userId: 'user_123',
477
+ email: 'user@example.com'
478
+ })
437
479
  if (!startResult.ok) { console.error(startResult.error); return }
438
480
 
439
481
  // 2. Ask user for the code
@@ -458,19 +500,19 @@ await fetch('/api/login', {
458
500
  ```typescript
459
501
  async function authenticateUser(userId: string) {
460
502
  if (!TryMellon.isSupported()) {
461
- return await authenticateWithEmail(userId)
503
+ return await authenticateWithEmail(userId, userId)
462
504
  }
463
505
 
464
506
  const authResult = await client.authenticate({ externalUserId: userId })
465
507
  if (authResult.ok) return authResult
466
508
  if (authResult.error.code === 'PASSKEY_NOT_FOUND' || authResult.error.code === 'NOT_SUPPORTED') {
467
- return await authenticateWithEmail(userId)
509
+ return await authenticateWithEmail(userId, userId)
468
510
  }
469
511
  return authResult
470
512
  }
471
513
 
472
- async function authenticateWithEmail(userId: string) {
473
- const startRes = await client.fallback.email.start({ userId })
514
+ async function authenticateWithEmail(userId: string, email: string) {
515
+ const startRes = await client.fallback.email.start({ userId, email })
474
516
  if (!startRes.ok) return startRes
475
517
  const code = prompt('Enter the code sent by email:')
476
518
  return await client.fallback.email.verify({ userId, code })
@@ -512,7 +554,7 @@ if (!pollResult.ok) {
512
554
  }
513
555
 
514
556
  // Success!
515
- console.log('Session token:', pollResult.value.session_token)
557
+ console.log('Session token:', pollResult.value.sessionToken)
516
558
  ```
517
559
 
518
560
  ### 2. Mobile: Approve Login
@@ -564,7 +606,10 @@ if (!result.ok) {
564
606
  console.log('User cancelled the operation')
565
607
  break
566
608
  case 'NOT_SUPPORTED':
567
- await client.fallback.email.start({ userId: 'user_123' })
609
+ await client.fallback.email.start({
610
+ userId: 'user_123',
611
+ email: 'user@example.com'
612
+ })
568
613
  break
569
614
  case 'PASSKEY_NOT_FOUND':
570
615
  await client.register({ externalUserId: 'user_123' })
@@ -696,7 +741,7 @@ If `TryMellon.isSupported()` returns `false`:
696
741
 
697
742
  - Ensure you are on HTTPS (required except on `localhost`)
698
743
  - Ensure your browser supports WebAuthn (Chrome, Safari, Firefox, Edge)
699
- - Use the email fallback: `client.fallback.email.start({ userId })`
744
+ - Use the email fallback: `client.fallback.email.start({ userId, email })`
700
745
 
701
746
  ### User cancelled the operation
702
747
 
@@ -711,7 +756,7 @@ If you get `PASSKEY_NOT_FOUND`:
711
756
 
712
757
  - The user has no registered passkey
713
758
  - Offer to register: `client.register()`
714
- - Or use email fallback: `client.fallback.email.start()`
759
+ - Or use email fallback: `client.fallback.email.start({ userId, email })`
715
760
 
716
761
  ### Network errors
717
762
 
@@ -784,6 +829,13 @@ Framework-specific: React uses `TryMellonProvider` + hooks; Vue uses `provideTry
784
829
 
785
830
  ---
786
831
 
832
+ ## Contact & landing
833
+
834
+ - **Landing:** [https://trymellon-landing.pages.dev/](https://trymellon-landing.pages.dev/)
835
+ - **Contact:** [siliangrove@gmail.com](mailto:siliangrove@gmail.com) — Sales inquiries by email only.
836
+
837
+ ---
838
+
787
839
  ## Additional documentation
788
840
 
789
841
  - [API Reference](./documentation/API.md) – Full API reference
package/dist/angular.cjs CHANGED
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- "use strict";var Ve=Object.create;var k=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames;var We=Object.prototype.hasOwnProperty;var Se=(e,r)=>(r=Symbol[e])?r:Symbol.for("Symbol."+e),L=e=>{throw TypeError(e)};var He=(e,r,t)=>r in e?k(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var _e=(e,r)=>k(e,"name",{value:r,configurable:!0});var Ye=(e,r)=>{for(var t in r)k(e,t,{get:r[t],enumerable:!0})},$e=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of Be(r))!We.call(e,s)&&s!==t&&k(e,s,{get:()=>r[s],enumerable:!(n=Ie(r,s))||n.enumerable});return e};var Ge=e=>$e(k({},"__esModule",{value:!0}),e);var Oe=e=>[,,,Ve(e?.[Se("metadata")]??null)],Ce=["class","method","getter","setter","accessor","field","value","get","set"],F=e=>e!==void 0&&typeof e!="function"?L("Function expected"):e,Xe=(e,r,t,n,s)=>({kind:Ce[e],name:r,metadata:n,addInitializer:i=>t._?L("Already initialized"):s.push(F(i||null))}),ze=(e,r)=>He(r,Se("metadata"),e[3]),Pe=(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},De=(e,r,t,n,s,i)=>{var a,d,l,h,g,m=r&7,A=!!(r&8),v=!!(r&16),M=m>3?e.length+1:m?A?1:2:0,I=Ce[m+5],U=m>3&&(e[M-1]=[]),Z=e[M]||(e[M]=[]),_=m&&(!v&&!A&&(s=s.prototype),m<5&&(m>3||!v)&&Ie(m<4?s:{get[t](){return Te(this,i)},set[t](b){return Ae(this,i,b)}},t));m?v&&m<4&&_e(i,(m>2?"set ":m>1?"get ":"")+t):_e(s,t);for(var Q=n.length-1;Q>=0;Q--)h=Xe(m,t,l={},e[3],Z),m&&(h.static=A,h.private=v,g=h.access={has:v?b=>Je(s,b):b=>t in b},m^3&&(g.get=v?b=>(m^1?Te:Ze)(b,s,m^4?i:_.get):b=>b[t]),m>2&&(g.set=v?(b,ee)=>Ae(b,s,ee,m^4?i:_.set):(b,ee)=>b[t]=ee)),d=(0,n[Q])(m?m<4?v?i:_[I]:m>4?void 0:{get:_.get,set:_.set}:s,h),l._=1,m^4||d===void 0?F(d)&&(m>4?U.unshift(d):m?v?i=d:_[I]=d:s=d):typeof d!="object"||d===null?L("Object expected"):(F(a=d.get)&&(_.get=a),F(a=d.set)&&(_.set=a),F(a=d.init)&&U.unshift(a));return m||ze(e,s),_&&k(s,t,_),v?m^4?i:_:s};var re=(e,r,t)=>r.has(e)||L("Cannot "+t),Je=(e,r)=>Object(r)!==r?L('Cannot use the "in" operator on this value'):e.has(r),Te=(e,r,t)=>(re(e,r,"read from private field"),t?t.call(e):r.get(e));var Ae=(e,r,t,n)=>(re(e,r,"write to private field"),n?n.call(e,t):r.set(e,t),t),Ze=(e,r,t)=>(re(e,r,"access private method"),t);var Ar={};Ye(Ar,{TRYMELLON_CONFIG:()=>K,TryMellonService:()=>D,provideTryMellonConfig:()=>Tr});module.exports=Ge(Ar);var N=require("@angular/core");var R=e=>({ok:!0,value:e}),c=e=>({ok:!1,error:e});var q=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)}},Qe={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",UNKNOWN_ERROR:"An unknown error occurred"};function y(e,r,t){return new q(e,r??Qe[e],t)}function er(e){return e instanceof q||typeof e=="object"&&e!==null&&"isTryMellonError"in e&&e.isTryMellonError===!0}function te(){return y("NOT_SUPPORTED")}function T(e,r){return y("INVALID_ARGUMENT",`Invalid argument: ${e} - ${r}`,{field:e,reason:r})}function Me(e){return y("UNKNOWN_ERROR",`Failed to ${e} credential`,{operation:e})}function ne(e){return y("NOT_SUPPORTED",`No base64 ${e==="encode"?"encoding":"decoding"} available`,{type:e})}function ke(e,r){try{let t=new URL(e);if(t.protocol!=="https:"&&t.protocol!=="http:")throw T(r,"must use http or https protocol")}catch(t){throw er(t)?t:T(r,"must be a valid URL")}}function j(e,r,t,n){if(e<t||e>n)throw T(r,`must be between ${t} and ${n}`)}function V(e,r){if(typeof e!="string"||e.length===0)throw T(r,"must be a non-empty string");if(!/^[A-Za-z0-9_-]+$/.test(e))throw T(r,"must be a valid base64url string")}var rr={NotAllowedError:"USER_CANCELLED",AbortError:"ABORTED",NotSupportedError:"NOT_SUPPORTED",SecurityError:"NOT_SUPPORTED",InvalidStateError:"UNKNOWN_ERROR",UnknownError:"UNKNOWN_ERROR"};function E(e){if(e instanceof DOMException){let r=e.name,t=e.message||"WebAuthn operation failed",n=rr[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 O(e){return typeof e=="number"&&Number.isFinite(e)}function B(e){return typeof e=="boolean"}function x(e){return Array.isArray(e)}function o(e,r){return c(y("NETWORK_FAILURE",e,{...r,originalData:r?.originalData}))}function p(e,r){return e[r]}function se(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,"rp");if(!f(n)||!u(n.name)||!u(n.id))return o("Invalid API response: challenge.rp must have name and id strings",{originalData:e});let s=p(t,"user");if(!f(s)||!u(s.id)||!u(s.name)||!u(s.displayName))return o("Invalid API response: challenge.user must have id, name, displayName strings",{originalData:e});let i=p(t,"challenge");if(!u(i))return o("Invalid API response: challenge.challenge must be string",{originalData:e});let a=p(t,"pubKeyCredParams");if(!x(a))return o("Invalid API response: challenge.pubKeyCredParams must be array",{originalData:e});for(let g of a)if(!f(g)||g.type!=="public-key"||!O(g.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});let d=t.timeout;if(d!==void 0&&!O(d))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let l=t.excludeCredentials;if(l!==void 0){if(!x(l))return o("Invalid API response: excludeCredentials must be array",{originalData:e});for(let g of l)if(!f(g)||g.type!=="public-key"||!u(g.id))return o("Invalid API response: excludeCredentials items must have id and type",{originalData:e})}let h=t.authenticatorSelection;return h!==void 0&&!f(h)?o("Invalid API response: authenticatorSelection must be object",{originalData:e}):R({session_id:r,challenge:{rp:n,user:s,challenge:i,pubKeyCredParams:a,...d!==void 0&&{timeout:d},...l!==void 0&&{excludeCredentials:l},...h!==void 0&&{authenticatorSelection:h}}})}function ie(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&&!x(i))return o("Invalid API response: allowCredentials must be array",{originalData:e});if(i){for(let l of i)if(!f(l)||l.type!=="public-key"||!u(l.id))return o("Invalid API response: allowCredentials items must have id and type",{originalData:e})}let a=t.timeout;if(a!==void 0&&!O(a))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let d=t.userVerification;return d!==void 0&&!["required","preferred","discouraged"].includes(String(d))?o("Invalid API response: userVerification must be required|preferred|discouraged",{originalData:e}):R({session_id:r,challenge:{challenge:n,rpId:s,allowCredentials:i??[],...a!==void 0&&{timeout:a},...d!==void 0&&{userVerification:d}}})}function oe(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});if(!f(s))return o("Invalid API response: user must be object",{field:"user",originalData:e});let i=p(s,"user_id"),a=p(s,"external_user_id");if(!u(i)||!u(a))return o("Invalid API response: user must have user_id and external_user_id strings",{originalData:e});let d=s.email,l=s.metadata;return d!==void 0&&!u(d)?o("Invalid API response: user.email must be string",{originalData:e}):l!==void 0&&(typeof l!="object"||l===null)?o("Invalid API response: user.metadata must be object",{originalData:e}):R({credential_id:r,status:t,session_token:n,user:{user_id:i,external_user_id:a,...d!==void 0&&{email:d},...l!==void 0&&{metadata:l}}})}function ae(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(!B(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});if(!f(n))return o("Invalid API response: user must be object",{field:"user",originalData:e});let i=p(n,"user_id"),a=p(n,"external_user_id");return!u(i)||!u(a)?o("Invalid API response: user must have user_id and external_user_id strings",{originalData:e}):s!==void 0&&!f(s)?o("Invalid API response: signals must be object",{originalData:e}):R({authenticated:r,session_token:t,user:{user_id:i,external_user_id:a,...n.email!==void 0&&{email:n.email},...n.metadata!==void 0&&{metadata:n.metadata}},signals:s})}function le(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 B(r)?u(t)?u(n)?u(s)?u(i)?R({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 ue(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=p(e,"sessionToken");return u(r)?R({sessionToken:r}):o("Invalid API response: sessionToken must be string",{field:"sessionToken",originalData:e})}var tr=["pending_passkey","pending_data","completed"],nr=["pending_data","completed"];function pe(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)?O(n)?R({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 ce(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)||!tr.includes(r)?o("Invalid API response: status must be pending_passkey|pending_data|completed",{field:"status",originalData:e}):u(t)?O(n)?R({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 de(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=sr(s);if(!a.ok)return a;i=a.value}return R({session_id:r,status:"pending_passkey",onboarding_url:n,...i!==void 0&&{challenge:i}})}function sr(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(!x(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"||!O(i.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});return R({rp:r,user:t,challenge:n,pubKeyCredParams:s})}function ge(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)||!nr.includes(t)?o("Invalid API response: status must be pending_data|completed",{originalData:e}):u(n)?u(s)?R({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 me(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}):R({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 fe(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=e.session_id,t=e.qr_url,n=e.expires_at;return!u(r)||!u(t)||!u(n)?o("Invalid API response: missing required fields",{originalData:e}):R({session_id:r,qr_url:t,expires_at:n})}function Re(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=e.status;return!u(r)||!["pending","authenticated","completed"].includes(r)?o("Invalid API response: invalid status",{originalData:e}):R({status:r,user_id:e.user_id,session_token:e.session_token})}function ye(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=e.options;return f(r)?R({options:r}):o("Invalid API response: options are required",{originalData:e})}var W=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,se)}async startAuth(r){return this.post("/v1/passkeys/auth/start",r,ie)}async finishRegister(r){return this.post("/v1/passkeys/register/finish",r,oe)}async finishAuthentication(r){return this.post("/v1/passkeys/auth/finish",r,ae)}async validateSession(r){return this.get("/v1/sessions/validate",le,{Authorization:`Bearer ${r}`})}async startEmailFallback(r){let t=`${this.baseUrl}/v1/fallback/email/start`,n=await this.httpClient.post(t,{userId:r},this.mergeHeaders());return n.ok?R(void 0):c(n.error)}async verifyEmailCode(r,t){return this.post("/v1/fallback/email/verify",{userId:r,code:t},ue)}async startOnboarding(r){return this.post("/onboarding/start",r,pe)}async getOnboardingStatus(r){return this.get(`/onboarding/${r}/status`,ce)}async getOnboardingRegister(r){return this.get(`/onboarding/${r}/register`,de)}async registerOnboardingPasskey(r,t){return this.post(`/onboarding/${r}/register-passkey`,t,ge)}async completeOnboarding(r,t){return this.post(`/onboarding/${r}/complete`,t,me)}async initCrossDeviceAuth(){return this.post("/v1/auth/cross-device/init",{},fe)}async getCrossDeviceStatus(r){return this.get(`/v1/auth/cross-device/status/${r}`,Re)}async getCrossDeviceContext(r){return this.get(`/v1/auth/cross-device/context/${r}`,ye)}async verifyCrossDeviceAuth(r){let t=`${this.baseUrl}/v1/auth/cross-device/verify`,n=await this.httpClient.post(t,r,this.mergeHeaders());return n.ok?R(void 0):c(n.error)}};var ir=3e4;function or(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`}function xe(e,r){let t=r*Math.pow(2,e);return Math.min(t,ir)}function ar(e,r){return e!=="GET"?!1:r>=500||r===429}var H=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=or(),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 d=0;d<=this.maxRetries;d++)try{let l=new AbortController,h=setTimeout(()=>l.abort(),this.timeoutMs),g=await fetch(r,{...t,headers:i,signal:l.signal});if(clearTimeout(h),!g.ok){let A;try{A=await g.json()}catch{}let v=A,M=v?.message??g.statusText,I=v?.error??"NETWORK_FAILURE",U=y(I,M,{requestId:s,status:g.status,statusText:g.statusText,data:A});if(ar(n,g.status)&&d<this.maxRetries){a=U,await new Promise(Z=>setTimeout(Z,xe(d,this.retryDelayMs)));continue}return c(U)}let m=await g.json();return R(m)}catch(l){if(a=l,n==="GET"&&d<this.maxRetries)await new Promise(g=>setTimeout(g,xe(d,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 C(){try{return!(typeof navigator>"u"||!navigator.credentials||typeof PublicKeyCredential>"u")}catch{return!1}}async function lr(){try{return!C()||typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable!="function"?!1:await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}async function we(){let e=C(),r=await lr();return{isPasskeySupported:e,platformAuthenticatorAvailable:r,recommendedFlow:e?"passkey":"fallback"}}function S(e){let r=new Uint8Array(e),t="";for(let s=0;s<r.length;s++)t+=String.fromCharCode(r[s]??0);let n="";if(typeof btoa<"u")n=btoa(t);else if(typeof Buffer<"u")n=Buffer.from(t,"binary").toString("base64");else throw ne("encode");return n.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function ur(e){let r=e.replace(/-/g,"+").replace(/_/g,"/"),t=r.length%4;t!==0&&(r+="=".repeat(4-t));let n="";if(typeof atob<"u")n=atob(r);else if(typeof Buffer<"u")n=Buffer.from(r,"base64").toString("binary");else throw ne("decode");let s=new Uint8Array(n.length);for(let i=0;i<n.length;i++)s[i]=n.charCodeAt(i);return s}function w(e){let r=ur(e),t=new ArrayBuffer(r.length);return new Uint8Array(t).set(r),t}function P(e,r="create"){if(!e||typeof e!="object"||!("id"in e)||!("rawId"in e)||!("response"in e))throw Me(r)}function Ne(e){return e!==null&&typeof e=="object"&&"clientDataJSON"in e&&e.clientDataJSON instanceof ArrayBuffer}function Y(e){if(!e.response)throw y("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!Ne(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:S(e.rawId),response:{clientDataJSON:S(t),attestationObject:S(n)},type:"public-key"}}function $(e){if(!e.response)throw y("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!Ne(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:S(e.rawId),response:{authenticatorData:S(n),clientDataJSON:S(t),signature:S(s),...i&&{userHandle:S(i)}},type:"public-key"}}function he(e,r){try{V(e.challenge,"challenge"),V(e.user.id,"user.id");let t=w(e.challenge),n=w(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:w(a.id),type:a.type,...a.transports&&{transports:a.transports}}))}};return R({publicKey:i})}catch(t){return c(E(t))}}function ve(e,r){try{V(e.challenge,"challenge");let t=w(e.challenge);return R({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:w(n.id),type:n.type,...n.transports&&{transports:n.transports}}))}},...r!==void 0&&{mediation:r}})}catch(t){return c(E(t))}}async function Ue(e,r,t){try{if(t.emit("start",{type:"start",operation:"register"}),!C()){let g=te();return t.emit("error",{type:"error",error:g}),c(g)}let n=e.externalUserId??e.external_user_id;if(!n)throw new Error("externalUserId is required");let s=await r.startRegister({external_user_id:n});if(!s.ok)return t.emit("error",{type:"error",error:s.error}),c(s.error);let i=he(s.value.challenge,e.authenticatorType);if(!i.ok)return t.emit("error",{type:"error",error:i.error}),c(i.error);let a=i.value;e.signal&&(a.signal=e.signal);let d=await navigator.credentials.create(a);if(!d){let g=T("credential","creation failed");return t.emit("error",{type:"error",error:g}),c(g)}try{P(d)}catch(g){let m=E(g);return t.emit("error",{type:"error",error:m}),c(m)}let l=await r.finishRegister({session_id:s.value.session_id,credential:Y(d)});if(!l.ok)return t.emit("error",{type:"error",error:l.error}),c(l.error);let h={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}};return t.emit("success",{type:"success",operation:"register"}),R(h)}catch(n){let s=E(n);return t.emit("error",{type:"error",error:s}),c(s)}}async function Fe(e,r,t){try{if(t.emit("start",{type:"start",operation:"authenticate"}),!C()){let g=te();return t.emit("error",{type:"error",error:g}),c(g)}let n=e.externalUserId??e.external_user_id;if(!n)throw new Error("externalUserId is required");let s=await r.startAuth({external_user_id:n});if(!s.ok)return t.emit("error",{type:"error",error:s.error}),c(s.error);let i=ve(s.value.challenge,e.mediation);if(!i.ok)return t.emit("error",{type:"error",error:i.error}),c(i.error);let a=i.value;e.signal&&(a.signal=e.signal);let d=await navigator.credentials.get(a);if(!d){let g=T("credential","retrieval failed");return t.emit("error",{type:"error",error:g}),c(g)}try{P(d)}catch(g){let m=E(g);return t.emit("error",{type:"error",error:m}),c(m)}let l=await r.finishAuthentication({session_id:s.value.session_id,credential:$(d)});if(!l.ok)return t.emit("error",{type:"error",error:l.error}),c(l.error);let h={authenticated:l.value.authenticated,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},signals:l.value.signals};return t.emit("success",{type:"success",operation:"authenticate"}),R(h)}catch(n){let s=E(n);return t.emit("error",{type:"error",error:s}),c(s)}}var pr=2e3,cr=60,G=class{constructor(r){this.apiClient=r}async startFlow(r){let t=await this.apiClient.startOnboarding({user_role:r.user_role});if(!t.ok)return c(t.error);let{session_id:n}=t.value;for(let s=0;s<cr;s++){await new Promise(l=>setTimeout(l,pr));let i=await this.apiClient.getOnboardingStatus(n);if(!i.ok)return c(i.error);let a=i.value.status,d=i.value.onboarding_url;if(a==="pending_passkey"){let l=await this.apiClient.getOnboardingRegister(n);if(!l.ok)return c(l.error);let h=l.value;if(!h.challenge)return c(y("NOT_SUPPORTED","Onboarding requires user action - complete passkey registration at the provided onboarding_url",{onboarding_url:d}));let g=he(h.challenge);if(!g.ok)return c(g.error);let m;try{m=await navigator.credentials.create(g.value)}catch(I){return c(E(I))}try{P(m,"create")}catch(I){return c(E(I))}let A;try{A=Y(m)}catch(I){return c(E(I))}let v=await this.apiClient.registerOnboardingPasskey(n,{credential:A,challenge:h.challenge.challenge});return v.ok?await this.apiClient.completeOnboarding(n,{company_name:r.company_name}):c(v.error)}if(a==="completed")return await this.apiClient.completeOnboarding(n,{company_name:r.company_name})}return c(y("TIMEOUT","Onboarding timed out"))}};var dr=2e3,gr=60,X=class{constructor(r){this.apiClient=r}async init(){return this.apiClient.initCrossDeviceAuth()}async waitForSession(r,t){for(let n=0;n<gr;n++){if(t?.aborted)return c(y("ABORT_ERROR","Operation aborted by user or timeout"));let s=await this.apiClient.getCrossDeviceStatus(r);if(!s.ok)return c(s.error);if(s.value.status==="completed")return!s.value.session_token||!s.value.user_id?c(y("UNKNOWN_ERROR","Missing data in completed session")):R({session_token:s.value.session_token,user_id:s.value.user_id});if(t?.aborted)return c(y("ABORT_ERROR","Operation aborted by user or timeout"));if(await new Promise(i=>{let a=setTimeout(()=>{i(null),t?.removeEventListener("abort",d)},dr),d=()=>{clearTimeout(a),i(null)};t?.addEventListener("abort",d)}),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=ve(t.value.options);if(!n.ok)return c(n.error);let s;try{s=await navigator.credentials.get(n.value)}catch(a){return c(E(a))}try{P(s,"get")}catch(a){return c(E(a))}let i;try{i=$(s)}catch(a){return c(E(a))}return this.apiClient.verifyCrossDeviceAuth({session_id:r,credential:i})}};var z=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);n&&n.forEach(s=>{try{s(t)}catch{}})}removeAllListeners(){this.handlers.clear()}};var Le="https://api.trymellonauth.com",Ke="https://api.trymellonauth.com/v1/telemetry";function qe(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 Ee(e,r){return{event:e,latencyMs:r,ok:!0}}var J=class{apiClient;eventEmitter;telemetrySender;crossDeviceManager;onboarding;constructor(r){let t=r.appId,n=r.publishableKey;if(!t||typeof t!="string"||t.trim()==="")throw T("appId","must be a non-empty string");if(!n||typeof n!="string"||n.trim()==="")throw T("publishableKey","must be a non-empty string");let s=r.apiBaseUrl??Le;ke(s,"apiBaseUrl");let i=r.timeoutMs??3e4;j(i,"timeoutMs",1e3,3e5),r.maxRetries!==void 0&&j(r.maxRetries,"maxRetries",0,10),r.retryDelayMs!==void 0&&j(r.retryDelayMs,"retryDelayMs",100,1e4);let a=r.maxRetries??3,d=r.retryDelayMs??1e3,l=new H(i,a,d,r.logger),h={"X-App-Id":t.trim(),Authorization:`Bearer ${n.trim()}`};this.apiClient=new W(l,s,h),this.onboarding=new G(this.apiClient),this.crossDeviceManager=new X(this.apiClient),this.eventEmitter=new z,r.enableTelemetry&&(this.telemetrySender=r.telemetrySender??qe(r.telemetryEndpoint??Ke))}static isSupported(){return C()}async register(r){let t=Date.now(),n=await Ue(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(Ee("register",Date.now()-t)).catch(()=>{}),n}async authenticate(r){let t=Date.now(),n=await Fe(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(Ee("authenticate",Date.now()-t)).catch(()=>{}),n}async validateSession(r){return this.apiClient.validateSession(r)}async getStatus(){return we()}on(r,t){return this.eventEmitter.on(r,t)}version(){return"1.2.1"}fallback={email:{start:async r=>this.apiClient.startEmailFallback(r.userId),verify:async r=>this.apiClient.verifyEmailCode(r.userId,r.code)}};auth={crossDevice:{init:()=>this.crossDeviceManager.init(),waitForSession:(r,t)=>this.crossDeviceManager.waitForSession(r,t),approve:r=>this.crossDeviceManager.approve(r)}}};var K=new N.InjectionToken("TRYMELLON_CONFIG"),je,be;je=[(0,N.Injectable)({providedIn:"root"})];var D=class{config=(0,N.inject)(K,{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 J(this.config)}return this._client}};be=Oe(null),D=De(be,0,"TryMellonService",je,D),Pe(be,1,D);function Tr(e){return{provide:K,useValue:e}}0&&(module.exports={TRYMELLON_CONFIG,TryMellonService,provideTryMellonConfig});
2
+ "use strict";var Je=Object.create;var k=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var Ze=Object.getOwnPropertyNames;var Qe=Object.prototype.hasOwnProperty;var xe=(e,r)=>(r=Symbol[e])?r:Symbol.for("Symbol."+e),K=e=>{throw TypeError(e)};var er=(e,r,t)=>r in e?k(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var Ae=(e,r)=>k(e,"name",{value:r,configurable:!0});var rr=(e,r)=>{for(var t in r)k(e,t,{get:r[t],enumerable:!0})},tr=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of Ze(r))!Qe.call(e,s)&&s!==t&&k(e,s,{get:()=>r[s],enumerable:!(n=Ce(r,s))||n.enumerable});return e};var nr=e=>tr(k({},"__esModule",{value:!0}),e);var Pe=e=>[,,,Je(e?.[xe("metadata")]??null)],Me=["class","method","getter","setter","accessor","field","value","get","set"],L=e=>e!==void 0&&typeof e!="function"?K("Function expected"):e,sr=(e,r,t,n,s)=>({kind:Me[e],name:r,metadata:n,addInitializer:i=>t._?K("Already initialized"):s.push(L(i||null))}),ir=(e,r)=>er(r,xe("metadata"),e[3]),De=(e,r,t,n)=>{for(var s=0,i=e[r>>1],l=i&&i.length;s<l;s++)r&1?i[s].call(t):n=i[s].call(t,n);return n},ke=(e,r,t,n,s,i)=>{var l,c,u,h,m,g=r&7,I=!!(r&8),v=!!(r&16),D=g>3?e.length+1:g?I?1:2:0,A=Me[g+5],F=g>3&&(e[D-1]=[]),Z=e[D]||(e[D]=[]),T=g&&(!v&&!I&&(s=s.prototype),g<5&&(g>3||!v)&&Ce(g<4?s:{get[t](){return Se(this,i)},set[t](_){return Oe(this,i,_)}},t));g?v&&g<4&&Ae(i,(g>2?"set ":g>1?"get ":"")+t):Ae(s,t);for(var Q=n.length-1;Q>=0;Q--)h=sr(g,t,u={},e[3],Z),g&&(h.static=I,h.private=v,m=h.access={has:v?_=>or(s,_):_=>t in _},g^3&&(m.get=v?_=>(g^1?Se:ar)(_,s,g^4?i:T.get):_=>_[t]),g>2&&(m.set=v?(_,ee)=>Oe(_,s,ee,g^4?i:T.set):(_,ee)=>_[t]=ee)),c=(0,n[Q])(g?g<4?v?i:T[A]:g>4?void 0:{get:T.get,set:T.set}:s,h),u._=1,g^4||c===void 0?L(c)&&(g>4?F.unshift(c):g?v?i=c:T[A]=c:s=c):typeof c!="object"||c===null?K("Object expected"):(L(l=c.get)&&(T.get=l),L(l=c.set)&&(T.set=l),L(l=c.init)&&F.unshift(l));return g||ir(e,s),T&&k(s,t,T),v?g^4?i:T:s};var re=(e,r,t)=>r.has(e)||K("Cannot "+t),or=(e,r)=>Object(r)!==r?K('Cannot use the "in" operator on this value'):e.has(r),Se=(e,r,t)=>(re(e,r,"read from private field"),t?t.call(e):r.get(e));var Oe=(e,r,t,n)=>(re(e,r,"write to private field"),n?n.call(e,t):r.set(e,t),t),ar=(e,r,t)=>(re(e,r,"access private method"),t);var Ar={};rr(Ar,{TRYMELLON_CONFIG:()=>q,TryMellonService:()=>M,provideTryMellonConfig:()=>Ir});module.exports=nr(Ar);var U=require("@angular/core");var f=e=>({ok:!0,value:e}),a=e=>({ok:!1,error:e});var j=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)}},lr={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",UNKNOWN_ERROR:"An unknown error occurred"};function y(e,r,t){return new j(e,r??lr[e],t)}function te(e){return e instanceof j||typeof e=="object"&&e!==null&&"isTryMellonError"in e&&e.isTryMellonError===!0}function ne(){return y("NOT_SUPPORTED")}function b(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 se(e){return y("NOT_SUPPORTED",`No base64 ${e==="encode"?"encoding":"decoding"} available`,{type:e})}function ie(e,r){try{let t=new URL(e);if(t.protocol!=="https:"&&t.protocol!=="http:")throw b(r,"must use http or https protocol")}catch(t){throw te(t)?t:b(r,"must be a valid URL")}}function C(e,r,t,n){if(!Number.isFinite(e))throw b(r,"must be a finite number");if(e<t||e>n)throw b(r,`must be between ${t} and ${n}`)}function B(e,r){if(typeof e!="string"||e.length===0)throw b(r,"must be a non-empty string");if(!/^[A-Za-z0-9_-]+$/.test(e))throw b(r,"must be a valid base64url string")}var ur={NotAllowedError:"USER_CANCELLED",AbortError:"ABORTED",NotSupportedError:"NOT_SUPPORTED",SecurityError:"NOT_SUPPORTED",InvalidStateError:"UNKNOWN_ERROR",UnknownError:"UNKNOWN_ERROR"};function E(e){if(e instanceof DOMException){let r=e.name,t=e.message||"WebAuthn operation failed",n=ur[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 R(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function p(e){return typeof e=="string"}function O(e){return typeof e=="number"&&Number.isFinite(e)}function V(e){return typeof e=="boolean"}function w(e){return Array.isArray(e)}function o(e,r){return a(y("UNKNOWN_ERROR",e,{...r,originalData:r?.originalData}))}function d(e,r){return e[r]}function oe(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"session_id");if(!p(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});let t=d(e,"challenge");if(!R(t))return o("Invalid API response: challenge must be object",{field:"challenge",originalData:e});let n=d(t,"rp");if(!R(n)||!p(n.name)||!p(n.id))return o("Invalid API response: challenge.rp must have name and id strings",{originalData:e});let s=d(t,"user");if(!R(s)||!p(s.id)||!p(s.name)||!p(s.displayName))return o("Invalid API response: challenge.user must have id, name, displayName strings",{originalData:e});let i=d(t,"challenge");if(!p(i))return o("Invalid API response: challenge.challenge must be string",{originalData:e});let l=d(t,"pubKeyCredParams");if(!w(l))return o("Invalid API response: challenge.pubKeyCredParams must be array",{originalData:e});for(let m of l)if(!R(m)||m.type!=="public-key"||!O(m.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});let c=t.timeout;if(c!==void 0&&!O(c))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let u=t.excludeCredentials;if(u!==void 0){if(!w(u))return o("Invalid API response: excludeCredentials must be array",{originalData:e});for(let m of u)if(!R(m)||m.type!=="public-key"||!p(m.id))return o("Invalid API response: excludeCredentials items must have id and type",{originalData:e})}let h=t.authenticatorSelection;return h!==void 0&&!R(h)?o("Invalid API response: authenticatorSelection must be object",{originalData:e}):f({session_id:r,challenge:{rp:n,user:s,challenge:i,pubKeyCredParams:l,...c!==void 0&&{timeout:c},...u!==void 0&&{excludeCredentials:u},...h!==void 0&&{authenticatorSelection:h}}})}function ae(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"session_id");if(!p(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});let t=d(e,"challenge");if(!R(t))return o("Invalid API response: challenge must be object",{field:"challenge",originalData:e});let n=d(t,"challenge"),s=d(t,"rpId"),i=t.allowCredentials;if(!p(n))return o("Invalid API response: challenge.challenge must be string",{originalData:e});if(!p(s))return o("Invalid API response: challenge.rpId must be string",{originalData:e});if(i!==void 0&&!w(i))return o("Invalid API response: allowCredentials must be array",{originalData:e});if(i){for(let u of i)if(!R(u)||u.type!=="public-key"||!p(u.id))return o("Invalid API response: allowCredentials items must have id and type",{originalData:e})}let l=t.timeout;if(l!==void 0&&!O(l))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let c=t.userVerification;return c!==void 0&&!["required","preferred","discouraged"].includes(String(c))?o("Invalid API response: userVerification must be required|preferred|discouraged",{originalData:e}):f({session_id:r,challenge:{challenge:n,rpId:s,allowCredentials:i??[],...l!==void 0&&{timeout:l},...c!==void 0&&{userVerification:c}}})}function le(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"credential_id"),t=d(e,"status"),n=d(e,"session_token"),s=d(e,"user");if(!p(r))return o("Invalid API response: credential_id must be string",{field:"credential_id",originalData:e});if(!p(t))return o("Invalid API response: status must be string",{field:"status",originalData:e});if(!p(n))return o("Invalid API response: session_token must be string",{field:"session_token",originalData:e});if(!R(s))return o("Invalid API response: user must be object",{field:"user",originalData:e});let i=d(s,"user_id"),l=d(s,"external_user_id");if(!p(i)||!p(l))return o("Invalid API response: user must have user_id and external_user_id strings",{originalData:e});let c=s.email,u=s.metadata;return c!==void 0&&!p(c)?o("Invalid API response: user.email must be string",{originalData:e}):u!==void 0&&(typeof u!="object"||u===null)?o("Invalid API response: user.metadata must be object",{originalData:e}):f({credential_id:r,status:t,session_token:n,user:{user_id:i,external_user_id:l,...c!==void 0&&{email:c},...u!==void 0&&{metadata:u}}})}function ue(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"authenticated"),t=d(e,"session_token"),n=d(e,"user"),s=d(e,"signals");if(!V(r))return o("Invalid API response: authenticated must be boolean",{field:"authenticated",originalData:e});if(!p(t))return o("Invalid API response: session_token must be string",{field:"session_token",originalData:e});if(!R(n))return o("Invalid API response: user must be object",{field:"user",originalData:e});let i=d(n,"user_id"),l=d(n,"external_user_id");return!p(i)||!p(l)?o("Invalid API response: user must have user_id and external_user_id strings",{originalData:e}):s!==void 0&&!R(s)?o("Invalid API response: signals must be object",{originalData:e}):f({authenticated:r,session_token:t,user:{user_id:i,external_user_id:l,...n.email!==void 0&&{email:n.email},...n.metadata!==void 0&&{metadata:n.metadata}},signals:s})}function pe(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"valid"),t=d(e,"user_id"),n=d(e,"external_user_id"),s=d(e,"tenant_id"),i=d(e,"app_id");return V(r)?p(t)?p(n)?p(s)?p(i)?f({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 de(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"sessionToken");return p(r)?f({sessionToken:r}):o("Invalid API response: sessionToken must be string",{field:"sessionToken",originalData:e})}var pr=["pending_passkey","pending_data","completed"],dr=["pending_data","completed"];function ce(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"session_id"),t=d(e,"onboarding_url"),n=d(e,"expires_in");return p(r)?p(t)?O(n)?f({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 me(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"status"),t=d(e,"onboarding_url"),n=d(e,"expires_in");return!p(r)||!pr.includes(r)?o("Invalid API response: status must be pending_passkey|pending_data|completed",{field:"status",originalData:e}):p(t)?O(n)?f({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 ge(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"session_id"),t=d(e,"status"),n=d(e,"onboarding_url");if(!p(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(!p(n))return o("Invalid API response: onboarding_url must be string",{originalData:e});let s=e.challenge,i;if(s!==void 0){let l=cr(s);if(!l.ok)return l;i=l.value}return f({session_id:r,status:"pending_passkey",onboarding_url:n,...i!==void 0&&{challenge:i}})}function cr(e){if(!R(e))return o("Invalid API response: challenge must be object",{originalData:e});let r=d(e,"rp"),t=d(e,"user"),n=d(e,"challenge"),s=d(e,"pubKeyCredParams");if(!R(r)||!p(r.name)||!p(r.id))return o("Invalid API response: challenge.rp must have name and id",{originalData:e});if(!R(t)||!p(t.id)||!p(t.name)||!p(t.displayName))return o("Invalid API response: challenge.user must have id, name, displayName",{originalData:e});if(!p(n))return o("Invalid API response: challenge.challenge must be string",{originalData:e});if(!w(s))return o("Invalid API response: challenge.pubKeyCredParams must be array",{originalData:e});for(let i of s)if(!R(i)||i.type!=="public-key"||!O(i.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});return f({rp:r,user:t,challenge:n,pubKeyCredParams:s})}function fe(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"session_id"),t=d(e,"status"),n=d(e,"user_id"),s=d(e,"tenant_id");return p(r)?!p(t)||!dr.includes(t)?o("Invalid API response: status must be pending_data|completed",{originalData:e}):p(n)?p(s)?f({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 Re(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=d(e,"session_id"),t=d(e,"status"),n=d(e,"user_id"),s=d(e,"tenant_id"),i=d(e,"session_token");return p(r)?t!=="completed"?o("Invalid API response: status must be completed",{originalData:e}):!p(n)||!p(s)||!p(i)?o("Invalid API response: user_id, tenant_id, session_token must be strings",{originalData:e}):f({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 ye(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=e.session_id,t=e.qr_url,n=e.expires_at;return!p(r)||!p(t)||!p(n)?o("Invalid API response: missing required fields",{originalData:e}):f({session_id:r,qr_url:t,expires_at:n})}function he(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=e.status;return!p(r)||!["pending","authenticated","completed"].includes(r)?o("Invalid API response: invalid status",{originalData:e}):f({status:r,user_id:e.user_id,session_token:e.session_token})}function be(e){if(!R(e))return o("Invalid API response: expected object",{originalData:e});let r=e.options;return R(r)?f({options:r}):o("Invalid API response: options are required",{originalData:e})}var W=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):a(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):a(i.error)}async startRegister(r){return this.post("/v1/passkeys/register/start",r,oe)}async startAuth(r){return this.post("/v1/passkeys/auth/start",r,ae)}async finishRegister(r){return this.post("/v1/passkeys/register/finish",r,le)}async finishAuthentication(r){return this.post("/v1/passkeys/auth/finish",r,ue)}async validateSession(r){return this.get("/v1/sessions/validate",pe,{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?f(void 0):a(n.error)}async verifyEmailCode(r,t){return this.post("/v1/fallback/email/verify",{userId:r,code:t},de)}async startOnboarding(r){return this.post("/onboarding/start",r,ce)}async getOnboardingStatus(r){return this.get(`/onboarding/${r}/status`,me)}async getOnboardingRegister(r){return this.get(`/onboarding/${r}/register`,ge)}async registerOnboardingPasskey(r,t){return this.post(`/onboarding/${r}/register-passkey`,t,fe)}async completeOnboarding(r,t){return this.post(`/onboarding/${r}/complete`,t,Re)}async initCrossDeviceAuth(){return this.post("/v1/auth/cross-device/init",{},ye)}async getCrossDeviceStatus(r){return this.get(`/v1/auth/cross-device/status/${r}`,he)}async getCrossDeviceContext(r){return this.get(`/v1/auth/cross-device/context/${r}`,be)}async verifyCrossDeviceAuth(r){let t=`${this.baseUrl}/v1/auth/cross-device/verify`,n=await this.httpClient.post(t,r,this.mergeHeaders());return n.ok?f(void 0):a(n.error)}};var mr=3e4;function gr(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`}function Ne(e,r){let t=r*Math.pow(2,e);return Math.min(t,mr)}function fr(e,r){return e!=="GET"?!1:r>=500||r===429}var H=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=gr(),i=new Headers(t.headers);i.set("X-Request-Id",s),this.logger&&this.logger.debug("request",{requestId:s,url:r,method:n});let l;for(let c=0;c<=this.maxRetries;c++)try{let u=new AbortController,h=setTimeout(()=>u.abort(),this.timeoutMs);try{let m=await fetch(r,{...t,headers:i,signal:u.signal});if(!m.ok){let I;try{I=await m.json()}catch{}let v=I,D=v?.message??m.statusText,A=v?.error??"NETWORK_FAILURE",F=y(A,D,{requestId:s,status:m.status,statusText:m.statusText,data:I});if(fr(n,m.status)&&c<this.maxRetries){l=F,await new Promise(Z=>setTimeout(Z,Ne(c,this.retryDelayMs)));continue}return a(F)}let g=await m.json();return f(g)}finally{clearTimeout(h)}}catch(u){if(l=u,n==="GET"&&c<this.maxRetries)await new Promise(m=>setTimeout(m,Ne(c,this.retryDelayMs)));else break}return l instanceof Error&&l.name==="AbortError"?a(y("TIMEOUT","Request timed out",{requestId:s})):a(y("NETWORK_FAILURE",l instanceof Error?l.message:"Request failed",{requestId:s,cause:l}))}};function x(){try{return!(typeof navigator>"u"||!navigator.credentials||typeof PublicKeyCredential>"u")}catch{return!1}}async function Rr(){try{return!x()||typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable!="function"?!1:await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}async function Ue(){let e=x(),r=await Rr();return{isPasskeySupported:e,platformAuthenticatorAvailable:r,recommendedFlow:e?"passkey":"fallback"}}function S(e){let r=new Uint8Array(e),t="";for(let s=0;s<r.length;s++)t+=String.fromCharCode(r[s]??0);let n="";if(typeof btoa<"u")n=btoa(t);else if(typeof Buffer<"u")n=Buffer.from(t,"binary").toString("base64");else throw se("encode");return n.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function yr(e){let r=e.replace(/-/g,"+").replace(/_/g,"/"),t=r.length%4;t!==0&&(r+="=".repeat(4-t));let n="";if(typeof atob<"u")n=atob(r);else if(typeof Buffer<"u")n=Buffer.from(r,"base64").toString("binary");else throw se("decode");let s=new Uint8Array(n.length);for(let i=0;i<n.length;i++)s[i]=n.charCodeAt(i);return s}function N(e){let r=yr(e),t=new ArrayBuffer(r.length);return new Uint8Array(t).set(r),t}function P(e,r="create"){if(!e||typeof e!="object"||!("id"in e)||!("rawId"in e)||!("response"in e))throw we(r)}function Fe(e){return e!==null&&typeof e=="object"&&"clientDataJSON"in e&&e.clientDataJSON instanceof ArrayBuffer}function Y(e){if(!e.response)throw y("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!Fe(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:S(e.rawId),response:{clientDataJSON:S(t),attestationObject:S(n)},type:"public-key"}}function $(e){if(!e.response)throw y("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!Fe(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:S(e.rawId),response:{authenticatorData:S(n),clientDataJSON:S(t),signature:S(s),...i&&{userHandle:S(i)}},type:"public-key"}}function ve(e,r){try{B(e.challenge,"challenge"),B(e.user.id,"user.id");let t=N(e.challenge),n=N(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(l=>({id:N(l.id),type:l.type,...l.transports&&{transports:l.transports}}))}};return f({publicKey:i})}catch(t){return a(E(t))}}function Ee(e,r){try{B(e.challenge,"challenge");let t=N(e.challenge);return f({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:N(n.id),type:n.type,...n.transports&&{transports:n.transports}}))}},...r!==void 0&&{mediation:r}})}catch(t){return a(E(t))}}async function Le(e,r,t){try{if(t.emit("start",{type:"start",operation:"register"}),!x()){let m=ne();return t.emit("error",{type:"error",error:m}),a(m)}let n=e.externalUserId??e.external_user_id;if(!n||typeof n!="string"||n.trim()===""){let m=b("externalUserId","must be a non-empty string");return t.emit("error",{type:"error",error:m}),a(m)}let s=await r.startRegister({external_user_id:n});if(!s.ok)return t.emit("error",{type:"error",error:s.error}),a(s.error);let i=ve(s.value.challenge,e.authenticatorType);if(!i.ok)return t.emit("error",{type:"error",error:i.error}),a(i.error);let l={...i.value,...e.signal&&{signal:e.signal}},c=await navigator.credentials.create(l);if(!c){let m=b("credential","creation failed");return t.emit("error",{type:"error",error:m}),a(m)}try{P(c)}catch(m){let g=E(m);return t.emit("error",{type:"error",error:g}),a(g)}let u=await r.finishRegister({session_id:s.value.session_id,credential:Y(c)});if(!u.ok)return t.emit("error",{type:"error",error:u.error}),a(u.error);let h={success:!0,credentialId:u.value.credential_id,credential_id:u.value.credential_id,status:u.value.status,sessionToken:u.value.session_token,user:{userId:u.value.user.user_id,externalUserId:u.value.user.external_user_id,email:u.value.user.email,metadata:u.value.user.metadata}};return t.emit("success",{type:"success",operation:"register"}),f(h)}catch(n){let s=E(n);return t.emit("error",{type:"error",error:s}),a(s)}}async function Ke(e,r,t){try{if(t.emit("start",{type:"start",operation:"authenticate"}),!x()){let m=ne();return t.emit("error",{type:"error",error:m}),a(m)}let n=e.externalUserId??e.external_user_id;if(!n||typeof n!="string"||n.trim()===""){let m=b("externalUserId","must be a non-empty string");return t.emit("error",{type:"error",error:m}),a(m)}let s=await r.startAuth({external_user_id:n});if(!s.ok)return t.emit("error",{type:"error",error:s.error}),a(s.error);let i=Ee(s.value.challenge,e.mediation);if(!i.ok)return t.emit("error",{type:"error",error:i.error}),a(i.error);let l={...i.value,...e.signal&&{signal:e.signal}},c=await navigator.credentials.get(l);if(!c){let m=b("credential","retrieval failed");return t.emit("error",{type:"error",error:m}),a(m)}try{P(c)}catch(m){let g=E(m);return t.emit("error",{type:"error",error:g}),a(g)}let u=await r.finishAuthentication({session_id:s.value.session_id,credential:$(c)});if(!u.ok)return t.emit("error",{type:"error",error:u.error}),a(u.error);let h={authenticated:u.value.authenticated,sessionToken:u.value.session_token,user:{userId:u.value.user.user_id,externalUserId:u.value.user.external_user_id,email:u.value.user.email,metadata:u.value.user.metadata},signals:u.value.signals};return t.emit("success",{type:"success",operation:"authenticate"}),f(h)}catch(n){let s=E(n);return t.emit("error",{type:"error",error:s}),a(s)}}var hr=2e3,br=60,G=class{constructor(r){this.apiClient=r}async startFlow(r){let t=await this.apiClient.startOnboarding({user_role:r.user_role});if(!t.ok)return a(t.error);let{session_id:n}=t.value;for(let s=0;s<br;s++){await new Promise(u=>setTimeout(u,hr));let i=await this.apiClient.getOnboardingStatus(n);if(!i.ok)return a(i.error);let l=i.value.status,c=i.value.onboarding_url;if(l==="pending_passkey"){let u=await this.apiClient.getOnboardingRegister(n);if(!u.ok)return a(u.error);let h=u.value;if(!h.challenge)return a(y("NOT_SUPPORTED","Onboarding requires user action - complete passkey registration at the provided onboarding_url",{onboarding_url:c}));let m=ve(h.challenge);if(!m.ok)return a(m.error);let g;try{g=await navigator.credentials.create(m.value)}catch(A){return a(E(A))}try{P(g,"create")}catch(A){return a(E(A))}let I;try{I=Y(g)}catch(A){return a(E(A))}let v=await this.apiClient.registerOnboardingPasskey(n,{credential:I,challenge:h.challenge.challenge});return v.ok?await this.apiClient.completeOnboarding(n,{company_name:r.company_name}):a(v.error)}if(l==="completed")return await this.apiClient.completeOnboarding(n,{company_name:r.company_name})}return a(y("TIMEOUT","Onboarding timed out"))}};var vr=2e3,Er=60,X=class{constructor(r){this.apiClient=r}async init(){return this.apiClient.initCrossDeviceAuth()}async waitForSession(r,t){for(let n=0;n<Er;n++){if(t?.aborted)return a(y("ABORT_ERROR","Operation aborted by user or timeout"));let s=await this.apiClient.getCrossDeviceStatus(r);if(!s.ok)return a(s.error);if(s.value.status==="completed")return!s.value.session_token||!s.value.user_id?a(y("UNKNOWN_ERROR","Missing data in completed session")):f({session_token:s.value.session_token,user_id:s.value.user_id});if(t?.aborted)return a(y("ABORT_ERROR","Operation aborted by user or timeout"));if(await new Promise(i=>{let l=setTimeout(()=>{i(null),t?.removeEventListener("abort",c)},vr),c=()=>{clearTimeout(l),i(null)};t?.addEventListener("abort",c)}),t?.aborted)return a(y("ABORT_ERROR","Operation aborted by user or timeout"))}return a(y("TIMEOUT","Cross-device authentication timed out"))}async approve(r){let t=await this.apiClient.getCrossDeviceContext(r);if(!t.ok)return a(t.error);let n=Ee(t.value.options);if(!n.ok)return a(n.error);let s;try{s=await navigator.credentials.get(n.value)}catch(l){return a(E(l))}try{P(s,"get")}catch(l){return a(E(l))}let i;try{i=$(s)}catch(l){return a(E(l))}return this.apiClient.verifyCrossDeviceAuth({session_id:r,credential:i})}};var z=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);n&&n.forEach(s=>{try{s(t)}catch{}})}removeAllListeners(){this.handlers.clear()}};var _e="https://api.trymellonauth.com",qe="https://api.trymellonauth.com/v1/telemetry";var je="trymellon_sandbox_session_token_v1";function Be(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 Te(e,r){return{event:e,latencyMs:r,ok:!0}}var J=class e{sandbox;sandboxToken;apiClient;eventEmitter;telemetrySender;crossDeviceManager;onboarding;static create(r){try{let t=r.appId,n=r.publishableKey;if(!t||typeof t!="string"||t.trim()==="")return a(b("appId","must be a non-empty string"));if(!n||typeof n!="string"||n.trim()==="")return a(b("publishableKey","must be a non-empty string"));let s=r.apiBaseUrl??_e;ie(s,"apiBaseUrl");let i=r.timeoutMs??3e4;return C(i,"timeoutMs",1e3,3e5),r.maxRetries!==void 0&&C(r.maxRetries,"maxRetries",0,10),r.retryDelayMs!==void 0&&C(r.retryDelayMs,"retryDelayMs",100,1e4),f(new e(r))}catch(t){return te(t)?a(t):a(b("config",t.message))}}constructor(r){this.sandbox=r.sandbox===!0,this.sandboxToken=this.sandbox&&r.sandboxToken!=null&&r.sandboxToken!==""?r.sandboxToken:je;let t=r.appId,n=r.publishableKey;if(!t||typeof t!="string"||t.trim()==="")throw b("appId","must be a non-empty string");if(!n||typeof n!="string"||n.trim()==="")throw b("publishableKey","must be a non-empty string");let s=r.apiBaseUrl??_e;ie(s,"apiBaseUrl");let i=r.timeoutMs??3e4;C(i,"timeoutMs",1e3,3e5),r.maxRetries!==void 0&&C(r.maxRetries,"maxRetries",0,10),r.retryDelayMs!==void 0&&C(r.retryDelayMs,"retryDelayMs",100,1e4);let l=r.maxRetries??3,c=r.retryDelayMs??1e3,u=new H(i,l,c,r.logger),h={"X-App-Id":t.trim(),Authorization:`Bearer ${n.trim()}`};this.apiClient=new W(u,s,h),this.onboarding=new G(this.apiClient),this.crossDeviceManager=new X(this.apiClient),this.eventEmitter=new z,r.enableTelemetry&&(this.telemetrySender=r.telemetrySender??Be(r.telemetryEndpoint??qe))}static isSupported(){return x()}async register(r){if(this.sandbox){let s=r.externalUserId??r.external_user_id??"sandbox";return Promise.resolve(f({success:!0,credentialId:"",status:"sandbox",sessionToken:this.sandboxToken,user:{userId:"sandbox-user",externalUserId:typeof s=="string"?s:"sandbox"}}))}let t=Date.now(),n=await Le(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(Te("register",Date.now()-t)).catch(()=>{}),n}async authenticate(r){if(this.sandbox){let s=r.externalUserId??r.external_user_id??"sandbox";return Promise.resolve(f({authenticated:!0,sessionToken:this.sandboxToken,user:{userId:"sandbox-user",externalUserId:typeof s=="string"?s:"sandbox"}}))}let t=Date.now(),n=await Ke(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(Te("authenticate",Date.now()-t)).catch(()=>{}),n}async validateSession(r){return this.sandbox&&r===this.sandboxToken?Promise.resolve(f({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 Ue()}on(r,t){return this.eventEmitter.on(r,t)}version(){return"1.3.1"}fallback={email:{start:async r=>this.apiClient.startEmailFallback(r),verify:async r=>this.apiClient.verifyEmailCode(r.userId,r.code)}};auth={crossDevice:{init:()=>this.crossDeviceManager.init(),waitForSession:(r,t)=>this.crossDeviceManager.waitForSession(r,t),approve:r=>this.crossDeviceManager.approve(r)}}};var q=new U.InjectionToken("TRYMELLON_CONFIG"),ze,Ie;ze=[(0,U.Injectable)({providedIn:"root"})];var M=class{config=(0,U.inject)(q,{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 J(this.config)}return this._client}};Ie=Pe(null),M=ke(Ie,0,"TryMellonService",ze,M),De(Ie,1,M);function Ir(e){return{provide:q,useValue:e}}0&&(module.exports={TRYMELLON_CONFIG,TryMellonService,provideTryMellonConfig});
3
3
  //# sourceMappingURL=angular.cjs.map