@trymellon/js 1.1.3 → 1.2.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 +207 -4
- package/dist/angular.cjs +1 -1
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +1 -1
- package/dist/angular.d.ts +1 -1
- package/dist/angular.js +1 -1
- package/dist/angular.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +101 -56
- package/dist/index.d.ts +101 -56
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/{trymellon-Ca4kob_K.d.cts → trymellon-BafnRVKw.d.cts} +99 -54
- package/dist/{trymellon-Ca4kob_K.d.ts → trymellon-BafnRVKw.d.ts} +99 -54
- package/dist/vue.d.cts +1 -1
- package/dist/vue.d.ts +1 -1
- package/package.json +1 -1
package/README.MD
CHANGED
|
@@ -49,6 +49,138 @@ npm install @trymellon/js
|
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
+
## Framework support & entry points
|
|
53
|
+
|
|
54
|
+
The SDK is **framework-agnostic**. Use the main entry for Vanilla JS, Svelte, or any environment; use framework-specific entry points for React, Vue, and Angular to get hooks/services and tree-shaking.
|
|
55
|
+
|
|
56
|
+
| Entry point | Use case | Exports |
|
|
57
|
+
|-------------|----------|---------|
|
|
58
|
+
| `@trymellon/js` | Vanilla JS, Svelte, Node, or any bundler | `TryMellon`, `TryMellon.isSupported()`, `Result`, `ok`, `err`, `isTryMellonError`, types |
|
|
59
|
+
| `@trymellon/js/react` | React 18+ | `TryMellonProvider`, `useTryMellon`, `useRegister`, `useAuthenticate` |
|
|
60
|
+
| `@trymellon/js/vue` | Vue 3 (Composition API) | `provideTryMellon`, `useTryMellon`, `useRegister`, `useAuthenticate`, `TryMellonKey` |
|
|
61
|
+
| `@trymellon/js/angular` | Angular (standalone or NgModule) | `TryMellonService`, `provideTryMellonConfig`, `TRYMELLON_CONFIG` |
|
|
62
|
+
|
|
63
|
+
**Runtime:** ESM and CJS supported. For UMD/script tag use `@trymellon/js/umd` or the built `dist/index.global.js` (exposes `window.TryMellon`).
|
|
64
|
+
|
|
65
|
+
### React
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm install @trymellon/js
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { TryMellon } from '@trymellon/js'
|
|
73
|
+
import { TryMellonProvider, useTryMellon, useRegister, useAuthenticate } from '@trymellon/js/react'
|
|
74
|
+
|
|
75
|
+
const client = new TryMellon({ appId: 'app_live_xxxx', publishableKey: 'key_live_xxxx' })
|
|
76
|
+
|
|
77
|
+
function App() {
|
|
78
|
+
return (
|
|
79
|
+
<TryMellonProvider client={client}>
|
|
80
|
+
<LoginForm />
|
|
81
|
+
</TryMellonProvider>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function LoginForm() {
|
|
86
|
+
const { execute: register, loading } = useRegister()
|
|
87
|
+
const { execute: authenticate } = useAuthenticate()
|
|
88
|
+
|
|
89
|
+
const onRegister = () => register({ externalUserId: 'user_123' })
|
|
90
|
+
const onLogin = () => authenticate({ externalUserId: 'user_123' })
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<>
|
|
94
|
+
<button onClick={onRegister} disabled={loading}>Register passkey</button>
|
|
95
|
+
<button onClick={onLogin} disabled={loading}>Sign in</button>
|
|
96
|
+
</>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
- **Requirements:** React 18+. Create a `TryMellon` instance (e.g. at app root), wrap your app (or auth subtree) with `TryMellonProvider` passing `client={client}`; then use `useTryMellon()`, `useRegister()`, and `useAuthenticate()` in children.
|
|
102
|
+
|
|
103
|
+
### Vue
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
npm install @trymellon/js
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```vue
|
|
110
|
+
<script setup lang="ts">
|
|
111
|
+
import { TryMellon } from '@trymellon/js'
|
|
112
|
+
import { provideTryMellon, useTryMellon, useRegister, useAuthenticate } from '@trymellon/js/vue'
|
|
113
|
+
|
|
114
|
+
const client = new TryMellon({ appId: 'app_live_xxxx', publishableKey: 'key_live_xxxx' })
|
|
115
|
+
provideTryMellon(client)
|
|
116
|
+
|
|
117
|
+
const { execute: register, loading } = useRegister()
|
|
118
|
+
const { execute: authenticate } = useAuthenticate()
|
|
119
|
+
|
|
120
|
+
const onRegister = () => register({ externalUserId: 'user_123' })
|
|
121
|
+
const onLogin = () => authenticate({ externalUserId: 'user_123' })
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<template>
|
|
125
|
+
<button @click="onRegister" :disabled="loading">Register passkey</button>
|
|
126
|
+
<button @click="onLogin" :disabled="loading">Sign in</button>
|
|
127
|
+
</template>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- **Requirements:** Vue 3 with Composition API. Create a `TryMellon` instance and call `provideTryMellon(client)` once (e.g. in root or a parent); then use `useTryMellon()`, `useRegister()`, and `useAuthenticate()` in components.
|
|
131
|
+
|
|
132
|
+
### Angular
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npm install @trymellon/js
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
In your app config (e.g. `app.config.ts` or root module):
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { provideTryMellonConfig } from '@trymellon/js/angular'
|
|
142
|
+
|
|
143
|
+
export const appConfig = {
|
|
144
|
+
providers: [
|
|
145
|
+
provideTryMellonConfig({
|
|
146
|
+
appId: 'app_live_xxxx',
|
|
147
|
+
publishableKey: 'key_live_xxxx',
|
|
148
|
+
}),
|
|
149
|
+
],
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
In a component or service:
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { TryMellonService } from '@trymellon/js/angular'
|
|
157
|
+
|
|
158
|
+
@Injectable({ providedIn: 'root' })
|
|
159
|
+
export class AuthService {
|
|
160
|
+
private tryMellon = inject(TryMellonService)
|
|
161
|
+
|
|
162
|
+
register(userId: string) {
|
|
163
|
+
return this.tryMellon.client.register({ externalUserId: userId })
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
authenticate(userId: string) {
|
|
167
|
+
return this.tryMellon.client.authenticate({ externalUserId: userId })
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- **Requirements:** Angular (standalone or NgModule). Add `provideTryMellonConfig(config)` to your app `providers`; inject `TryMellonService` and use `.client` for `register()`, `authenticate()`, and other methods.
|
|
173
|
+
|
|
174
|
+
### Vanilla JavaScript
|
|
175
|
+
|
|
176
|
+
Use the main entry and instantiate `TryMellon` directly (see Quickstart below). Works in any ES module or CJS environment. For script-tag usage, use the UMD build: `@trymellon/js/umd` or `dist/index.global.js`; the global is `window.TryMellon`.
|
|
177
|
+
|
|
178
|
+
### Svelte (and other frameworks)
|
|
179
|
+
|
|
180
|
+
No dedicated adapter. Use the **main entry** `@trymellon/js`: create one `TryMellon` instance (e.g. in a module or store) and call `register()` / `authenticate()` from your components. Same API as Quickstart; no provider required.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
52
184
|
## Quickstart (5 minutes)
|
|
53
185
|
|
|
54
186
|
```bash
|
|
@@ -347,6 +479,62 @@ async function authenticateWithEmail(userId: string) {
|
|
|
347
479
|
|
|
348
480
|
---
|
|
349
481
|
|
|
482
|
+
## Cross-Device Authentication (QR Login)
|
|
483
|
+
|
|
484
|
+
Enable users to sign in on a desktop device by scanning a QR code with their mobile phone (where their passkey is stored).
|
|
485
|
+
|
|
486
|
+
### 1. Desktop: Initialize and Show QR
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
// Initialize session
|
|
490
|
+
const initResult = await client.auth.crossDevice.init()
|
|
491
|
+
if (!initResult.ok) { console.error(initResult.error); return }
|
|
492
|
+
|
|
493
|
+
const { session_id, qr_url } = initResult.value
|
|
494
|
+
|
|
495
|
+
// Show QR code with `qr_url`
|
|
496
|
+
renderQrCode(qr_url)
|
|
497
|
+
|
|
498
|
+
// Start polling for approval
|
|
499
|
+
// Use AbortController to cancel if user leaves the page
|
|
500
|
+
const controller = new AbortController()
|
|
501
|
+
|
|
502
|
+
const pollResult = await client.auth.crossDevice.waitForSession(
|
|
503
|
+
session_id,
|
|
504
|
+
controller.signal
|
|
505
|
+
)
|
|
506
|
+
|
|
507
|
+
if (!pollResult.ok) {
|
|
508
|
+
if (pollResult.error.code === 'TIMEOUT') {
|
|
509
|
+
showError('QR code expired')
|
|
510
|
+
}
|
|
511
|
+
return
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Success!
|
|
515
|
+
console.log('Session token:', pollResult.value.session_token)
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### 2. Mobile: Approve Login
|
|
519
|
+
|
|
520
|
+
When the user scans the QR code, your mobile web app should handle the URL (containing `session_id`) and call `approve`:
|
|
521
|
+
|
|
522
|
+
```typescript
|
|
523
|
+
// Extract session_id from URL query params
|
|
524
|
+
const sessionId = getSessionIdFromUrl()
|
|
525
|
+
|
|
526
|
+
// Trigger WebAuthn flow on mobile
|
|
527
|
+
const approveResult = await client.auth.crossDevice.approve(sessionId)
|
|
528
|
+
|
|
529
|
+
if (approveResult.ok) {
|
|
530
|
+
showSuccess('Process complete! Check your desktop.')
|
|
531
|
+
} else {
|
|
532
|
+
showError('Failed to approve login: ' + approveResult.error.message)
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
350
538
|
## Result type
|
|
351
539
|
|
|
352
540
|
The SDK exports the `Result<T, E>` type and the `ok(value)` and `err(error)` helpers for typing and building results (useful in tests or utilities):
|
|
@@ -486,15 +674,16 @@ Then create your own session in your system.
|
|
|
486
674
|
|
|
487
675
|
## Features
|
|
488
676
|
|
|
489
|
-
* ✅ **Zero runtime dependencies** – No external runtime dependencies
|
|
490
|
-
* ✅ **TypeScript first** – Full types and strict mode
|
|
491
|
-
* ✅ **Framework
|
|
677
|
+
* ✅ **Zero runtime dependencies** – No external runtime dependencies in the core bundle
|
|
678
|
+
* ✅ **TypeScript first** – Full types and strict mode; all entry points typed
|
|
679
|
+
* ✅ **Framework support** – Dedicated entry points: `@trymellon/js` (core), `@trymellon/js/react`, `@trymellon/js/vue`, `@trymellon/js/angular`; Vanilla and Svelte use core
|
|
492
680
|
* ✅ **Automatic retries** – Exponential backoff for transient errors
|
|
493
681
|
* ✅ **Thorough validation** – Input and API response validation
|
|
494
682
|
* ✅ **Robust error handling** – Typed, descriptive errors
|
|
495
683
|
* ✅ **Events for UX** – Event system for spinners and analytics
|
|
496
684
|
* ✅ **Email fallback** – OTP by email when WebAuthn is unavailable
|
|
497
685
|
* ✅ **Operation cancellation** – AbortSignal support
|
|
686
|
+
* ✅ **Cross-Device Auth** – QR Login flow support (Desktop to Mobile)
|
|
498
687
|
* ✅ **Automatic detection** – Origin and WebAuthn support detected automatically
|
|
499
688
|
|
|
500
689
|
---
|
|
@@ -581,10 +770,24 @@ The SDK can send anonymous telemetry (event + latency, no user identifiers) when
|
|
|
581
770
|
|
|
582
771
|
---
|
|
583
772
|
|
|
773
|
+
## Specification summary (for project ingestion)
|
|
774
|
+
|
|
775
|
+
Projects integrating this SDK should document in their README:
|
|
776
|
+
|
|
777
|
+
- **SDK:** `@trymellon/js` (and optionally `/react`, `/vue`, `/angular` if using those entry points)
|
|
778
|
+
- **Node:** >= 18 (per `engines`)
|
|
779
|
+
- **Browsers:** WebAuthn-capable (Chrome, Safari, Firefox, Edge); HTTPS required except `localhost`
|
|
780
|
+
- **Config:** `appId` and `publishableKey` from TryMellon dashboard; optional `apiBaseUrl` for self-hosted API
|
|
781
|
+
- **Backend:** Must validate `session_token` via TryMellon API (`GET /v1/sessions/validate`) and create own session
|
|
782
|
+
|
|
783
|
+
Framework-specific: React uses `TryMellonProvider` + hooks; Vue uses `provideTryMellon` + composables; Angular uses `provideTryMellonConfig` + `TryMellonService`; Vanilla/Svelte use core `TryMellon` only.
|
|
784
|
+
|
|
785
|
+
---
|
|
786
|
+
|
|
584
787
|
## Additional documentation
|
|
585
788
|
|
|
586
789
|
- [API Reference](./documentation/API.md) – Full API reference
|
|
587
|
-
- [Usage examples](./documentation/EXAMPLES.md) – Practical integration examples
|
|
790
|
+
- [Usage examples](./documentation/EXAMPLES.md) – Practical integration examples (React, Vue, Vanilla, events, fallback)
|
|
588
791
|
- [Contributing](./documentation/CONTRIBUTING.md) – How to contribute (including running tests, coverage, Angular, E2E, audit and workflow lint locally)
|
|
589
792
|
- [CI standards (fintech)](./documentation/CI-FINTECH-STANDARDS.md) – Coverage, security, E2E and workflow validation criteria
|
|
590
793
|
|
package/dist/angular.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";var Fe=Object.create;var C=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var Le=Object.getOwnPropertyNames;var Ke=Object.prototype.hasOwnProperty;var be=(e,r)=>(r=Symbol[e])?r:Symbol.for("Symbol."+e),F=e=>{throw TypeError(e)};var je=(e,r,t)=>r in e?C(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var Re=(e,r)=>C(e,"name",{value:r,configurable:!0});var qe=(e,r)=>{for(var t in r)C(e,t,{get:r[t],enumerable:!0})},Ve=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of Le(r))!Ke.call(e,s)&&s!==t&&C(e,s,{get:()=>r[s],enumerable:!(n=Ee(r,s))||n.enumerable});return e};var We=e=>Ve(C({},"__esModule",{value:!0}),e);var _e=e=>[,,,Fe(e?.[be("metadata")]??null)],Te=["class","method","getter","setter","accessor","field","value","get","set"],U=e=>e!==void 0&&typeof e!="function"?F("Function expected"):e,Be=(e,r,t,n,s)=>({kind:Te[e],name:r,metadata:n,addInitializer:i=>t._?F("Already initialized"):s.push(U(i||null))}),Ye=(e,r)=>je(r,be("metadata"),e[3]),ve=(e,r,t,n)=>{for(var s=0,i=e[r>>1],u=i&&i.length;s<u;s++)r&1?i[s].call(t):n=i[s].call(t,n);return n},Ae=(e,r,t,n,s,i)=>{var u,p,g,y,m,d=r&7,_=!!(r&8),R=!!(r&16),E=d>3?e.length+1:d?_?1:2:0,S=Te[d+5],N=d>3&&(e[E-1]=[]),z=e[E]||(e[E]=[]),A=d&&(!R&&!_&&(s=s.prototype),d<5&&(d>3||!R)&&Ee(d<4?s:{get[t](){return ye(this,i)},set[t](v){return he(this,i,v)}},t));d?R&&d<4&&Re(i,(d>2?"set ":d>1?"get ":"")+t):Re(s,t);for(var J=n.length-1;J>=0;J--)y=Be(d,t,g={},e[3],z),d&&(y.static=_,y.private=R,m=y.access={has:R?v=>He(s,v):v=>t in v},d^3&&(m.get=R?v=>(d^1?ye:Ge)(v,s,d^4?i:A.get):v=>v[t]),d>2&&(m.set=R?(v,Z)=>he(v,s,Z,d^4?i:A.set):(v,Z)=>v[t]=Z)),p=(0,n[J])(d?d<4?R?i:A[S]:d>4?void 0:{get:A.get,set:A.set}:s,y),g._=1,d^4||p===void 0?U(p)&&(d>4?N.unshift(p):d?R?i=p:A[S]=p:s=p):typeof p!="object"||p===null?F("Object expected"):(U(u=p.get)&&(A.get=u),U(u=p.set)&&(A.set=u),U(u=p.init)&&N.unshift(u));return d||Ye(e,s),A&&C(s,t,A),R?d^4?i:A:s};var Q=(e,r,t)=>r.has(e)||F("Cannot "+t),He=(e,r)=>Object(r)!==r?F('Cannot use the "in" operator on this value'):e.has(r),ye=(e,r,t)=>(Q(e,r,"read from private field"),t?t.call(e):r.get(e));var he=(e,r,t,n)=>(Q(e,r,"write to private field"),n?n.call(e,t):r.set(e,t),t),Ge=(e,r,t)=>(Q(e,r,"access private method"),t);var hr={};qe(hr,{TRYMELLON_CONFIG:()=>K,TryMellonService:()=>M,provideTryMellonConfig:()=>yr});module.exports=We(hr);var D=require("@angular/core");var h=e=>({ok:!0,value:e}),c=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)}},$e={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",UNKNOWN_ERROR:"An unknown error occurred"};function b(e,r,t){return new j(e,r??$e[e],t)}function Xe(e){return e instanceof j||typeof e=="object"&&e!==null&&"isTryMellonError"in e&&e.isTryMellonError===!0}function ee(){return b("NOT_SUPPORTED")}function I(e,r){return b("INVALID_ARGUMENT",`Invalid argument: ${e} - ${r}`,{field:e,reason:r})}function Ie(e){return b("UNKNOWN_ERROR",`Failed to ${e} credential`,{operation:e})}function re(e){return b("NOT_SUPPORTED",`No base64 ${e==="encode"?"encoding":"decoding"} available`,{type:e})}function Se(e,r){try{let t=new URL(e);if(t.protocol!=="https:"&&t.protocol!=="http:")throw I(r,"must use http or https protocol")}catch(t){throw Xe(t)?t:I(r,"must be a valid URL")}}function q(e,r,t,n){if(e<t||e>n)throw I(r,`must be between ${t} and ${n}`)}function V(e,r){if(typeof e!="string"||e.length===0)throw I(r,"must be a non-empty string");if(!/^[A-Za-z0-9_-]+$/.test(e))throw I(r,"must be a valid base64url string")}var ze={NotAllowedError:"USER_CANCELLED",AbortError:"ABORTED",NotSupportedError:"NOT_SUPPORTED",SecurityError:"NOT_SUPPORTED",InvalidStateError:"UNKNOWN_ERROR",UnknownError:"UNKNOWN_ERROR"};function T(e){if(e instanceof DOMException){let r=e.name,t=e.message||"WebAuthn operation failed",n=ze[r]??"UNKNOWN_ERROR";return b(n,t,{originalError:e})}return e instanceof Error?b("UNKNOWN_ERROR",e.message,{originalError:e}):b("UNKNOWN_ERROR","An unknown error occurred",{originalError:e})}function f(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function l(e){return typeof e=="string"}function P(e){return typeof e=="number"&&Number.isFinite(e)}function W(e){return typeof e=="boolean"}function w(e){return Array.isArray(e)}function o(e,r){return c(b("NETWORK_FAILURE",e,{...r,originalData:r?.originalData}))}function a(e,r){return e[r]}function te(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"session_id");if(!l(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});let t=a(e,"challenge");if(!f(t))return o("Invalid API response: challenge must be object",{field:"challenge",originalData:e});let n=a(t,"rp");if(!f(n)||!l(n.name)||!l(n.id))return o("Invalid API response: challenge.rp must have name and id strings",{originalData:e});let s=a(t,"user");if(!f(s)||!l(s.id)||!l(s.name)||!l(s.displayName))return o("Invalid API response: challenge.user must have id, name, displayName strings",{originalData:e});let i=a(t,"challenge");if(!l(i))return o("Invalid API response: challenge.challenge must be string",{originalData:e});let u=a(t,"pubKeyCredParams");if(!w(u))return o("Invalid API response: challenge.pubKeyCredParams must be array",{originalData:e});for(let m of u)if(!f(m)||m.type!=="public-key"||!P(m.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});let p=t.timeout;if(p!==void 0&&!P(p))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let g=t.excludeCredentials;if(g!==void 0){if(!w(g))return o("Invalid API response: excludeCredentials must be array",{originalData:e});for(let m of g)if(!f(m)||m.type!=="public-key"||!l(m.id))return o("Invalid API response: excludeCredentials items must have id and type",{originalData:e})}let y=t.authenticatorSelection;return y!==void 0&&!f(y)?o("Invalid API response: authenticatorSelection must be object",{originalData:e}):h({session_id:r,challenge:{rp:n,user:s,challenge:i,pubKeyCredParams:u,...p!==void 0&&{timeout:p},...g!==void 0&&{excludeCredentials:g},...y!==void 0&&{authenticatorSelection:y}}})}function ne(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"session_id");if(!l(r))return o("Invalid API response: session_id must be string",{field:"session_id",originalData:e});let t=a(e,"challenge");if(!f(t))return o("Invalid API response: challenge must be object",{field:"challenge",originalData:e});let n=a(t,"challenge"),s=a(t,"rpId"),i=t.allowCredentials;if(!l(n))return o("Invalid API response: challenge.challenge must be string",{originalData:e});if(!l(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 g of i)if(!f(g)||g.type!=="public-key"||!l(g.id))return o("Invalid API response: allowCredentials items must have id and type",{originalData:e})}let u=t.timeout;if(u!==void 0&&!P(u))return o("Invalid API response: challenge.timeout must be number",{originalData:e});let p=t.userVerification;return p!==void 0&&!["required","preferred","discouraged"].includes(String(p))?o("Invalid API response: userVerification must be required|preferred|discouraged",{originalData:e}):h({session_id:r,challenge:{challenge:n,rpId:s,allowCredentials:i??[],...u!==void 0&&{timeout:u},...p!==void 0&&{userVerification:p}}})}function se(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"credential_id"),t=a(e,"status"),n=a(e,"session_token"),s=a(e,"user");if(!l(r))return o("Invalid API response: credential_id must be string",{field:"credential_id",originalData:e});if(!l(t))return o("Invalid API response: status must be string",{field:"status",originalData:e});if(!l(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=a(s,"user_id"),u=a(s,"external_user_id");if(!l(i)||!l(u))return o("Invalid API response: user must have user_id and external_user_id strings",{originalData:e});let p=s.email,g=s.metadata;return p!==void 0&&!l(p)?o("Invalid API response: user.email must be string",{originalData:e}):g!==void 0&&(typeof g!="object"||g===null)?o("Invalid API response: user.metadata must be object",{originalData:e}):h({credential_id:r,status:t,session_token:n,user:{user_id:i,external_user_id:u,...p!==void 0&&{email:p},...g!==void 0&&{metadata:g}}})}function ie(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"authenticated"),t=a(e,"session_token"),n=a(e,"user"),s=a(e,"signals");if(!W(r))return o("Invalid API response: authenticated must be boolean",{field:"authenticated",originalData:e});if(!l(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=a(n,"user_id"),u=a(n,"external_user_id");return!l(i)||!l(u)?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}):h({authenticated:r,session_token:t,user:{user_id:i,external_user_id:u,...n.email!==void 0&&{email:n.email},...n.metadata!==void 0&&{metadata:n.metadata}},signals:s})}function oe(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"valid"),t=a(e,"user_id"),n=a(e,"external_user_id"),s=a(e,"tenant_id"),i=a(e,"app_id");return W(r)?l(t)?l(n)?l(s)?l(i)?h({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 ae(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"sessionToken");return l(r)?h({sessionToken:r}):o("Invalid API response: sessionToken must be string",{field:"sessionToken",originalData:e})}var Je=["pending_passkey","pending_data","completed"],Ze=["pending_data","completed"];function le(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"session_id"),t=a(e,"onboarding_url"),n=a(e,"expires_in");return l(r)?l(t)?P(n)?h({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 ue(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"status"),t=a(e,"onboarding_url"),n=a(e,"expires_in");return!l(r)||!Je.includes(r)?o("Invalid API response: status must be pending_passkey|pending_data|completed",{field:"status",originalData:e}):l(t)?P(n)?h({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 pe(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"session_id"),t=a(e,"status"),n=a(e,"onboarding_url");if(!l(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(!l(n))return o("Invalid API response: onboarding_url must be string",{originalData:e});let s=e.challenge,i;if(s!==void 0){let u=Qe(s);if(!u.ok)return u;i=u.value}return h({session_id:r,status:"pending_passkey",onboarding_url:n,...i!==void 0&&{challenge:i}})}function Qe(e){if(!f(e))return o("Invalid API response: challenge must be object",{originalData:e});let r=a(e,"rp"),t=a(e,"user"),n=a(e,"challenge"),s=a(e,"pubKeyCredParams");if(!f(r)||!l(r.name)||!l(r.id))return o("Invalid API response: challenge.rp must have name and id",{originalData:e});if(!f(t)||!l(t.id)||!l(t.name)||!l(t.displayName))return o("Invalid API response: challenge.user must have id, name, displayName",{originalData:e});if(!l(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(!f(i)||i.type!=="public-key"||!P(i.alg))return o("Invalid API response: pubKeyCredParams items must have type and alg",{originalData:e});return h({rp:r,user:t,challenge:n,pubKeyCredParams:s})}function de(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"session_id"),t=a(e,"status"),n=a(e,"user_id"),s=a(e,"tenant_id");return l(r)?!l(t)||!Ze.includes(t)?o("Invalid API response: status must be pending_data|completed",{originalData:e}):l(n)?l(s)?h({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 ce(e){if(!f(e))return o("Invalid API response: expected object",{originalData:e});let r=a(e,"session_id"),t=a(e,"status"),n=a(e,"user_id"),s=a(e,"tenant_id"),i=a(e,"session_token");return l(r)?t!=="completed"?o("Invalid API response: status must be completed",{originalData:e}):!l(n)||!l(s)||!l(i)?o("Invalid API response: user_id, tenant_id, session_token must be strings",{originalData:e}):h({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})}var B=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,te)}async startAuth(r){return this.post("/v1/passkeys/auth/start",r,ne)}async finishRegister(r){return this.post("/v1/passkeys/register/finish",r,se)}async finishAuth(r){return this.post("/v1/passkeys/auth/finish",r,ie)}async validateSession(r){return this.get("/v1/sessions/validate",oe,{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?h(void 0):c(n.error)}async verifyEmailCode(r,t){return this.post("/v1/fallback/email/verify",{userId:r,code:t},ae)}async startOnboarding(r){return this.post("/onboarding/start",r,le)}async getOnboardingStatus(r){return this.get(`/onboarding/${r}/status`,ue)}async getOnboardingRegister(r){return this.get(`/onboarding/${r}/register`,pe)}async registerOnboardingPasskey(r,t){return this.post(`/onboarding/${r}/register-passkey`,t,de)}async completeOnboarding(r,t){return this.post(`/onboarding/${r}/complete`,t,ce)}};var er=3e4;function rr(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2,11)}`}function Oe(e,r){let t=r*Math.pow(2,e);return Math.min(t,er)}function tr(e,r){return e!=="GET"?!1:r>=500||r===429}var Y=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=rr(),i=new Headers(t.headers);i.set("X-Request-Id",s),this.logger&&this.logger.debug("request",{requestId:s,url:r,method:n});let u;for(let p=0;p<=this.maxRetries;p++)try{let g=new AbortController,y=setTimeout(()=>g.abort(),this.timeoutMs),m=await fetch(r,{...t,headers:i,signal:g.signal});if(clearTimeout(y),!m.ok){let _;try{_=await m.json()}catch{}let R=_,E=R?.message??m.statusText,S=R?.error??"NETWORK_FAILURE",N=b(S,E,{requestId:s,status:m.status,statusText:m.statusText,data:_});if(tr(n,m.status)&&p<this.maxRetries){u=N,await new Promise(z=>setTimeout(z,Oe(p,this.retryDelayMs)));continue}return c(N)}let d=await m.json();return h(d)}catch(g){if(u=g,n==="GET"&&p<this.maxRetries)await new Promise(m=>setTimeout(m,Oe(p,this.retryDelayMs)));else break}return u instanceof Error&&u.name==="AbortError"?c(b("TIMEOUT","Request timed out",{requestId:s})):c(b("NETWORK_FAILURE",u instanceof Error?u.message:"Request failed",{requestId:s,cause:u}))}};function k(){try{return!(typeof navigator>"u"||!navigator.credentials||typeof PublicKeyCredential>"u")}catch{return!1}}async function nr(){try{return!k()||typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable!="function"?!1:await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()}catch{return!1}}async function Pe(){let e=k(),r=await nr();return{isPasskeySupported:e,platformAuthenticatorAvailable:r,recommendedFlow:e?"passkey":"fallback"}}function O(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 re("encode");return n.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function sr(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 re("decode");let s=new Uint8Array(n.length);for(let i=0;i<n.length;i++)s[i]=n.charCodeAt(i);return s}function x(e){let r=sr(e),t=new ArrayBuffer(r.length);return new Uint8Array(t).set(r),t}function L(e,r="create"){if(!e||typeof e!="object"||!("id"in e)||!("rawId"in e)||!("response"in e))throw Ie(r)}function ke(e){return e!==null&&typeof e=="object"&&"clientDataJSON"in e&&e.clientDataJSON instanceof ArrayBuffer}function H(e){if(!e.response)throw b("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!ke(r))throw b("UNKNOWN_ERROR","Invalid credential response structure",{response:r});if(!("attestationObject"in r))throw b("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:O(e.rawId),response:{clientDataJSON:O(t),attestationObject:O(n)},type:"public-key"}}function Me(e){if(!e.response)throw b("UNKNOWN_ERROR","Credential response is missing",{credential:e});let r=e.response;if(!ke(r))throw b("UNKNOWN_ERROR","Invalid credential response structure",{response:r});if(!("authenticatorData"in r)||!("signature"in r))throw b("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:O(e.rawId),response:{authenticatorData:O(n),clientDataJSON:O(t),signature:O(s),...i&&{userHandle:O(i)}},type:"public-key"}}function ge(e,r){try{V(e.challenge,"challenge"),V(e.user.id,"user.id");let t=x(e.challenge),n=x(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(u=>({id:x(u.id),type:u.type,...u.transports&&{transports:u.transports}}))}};return h({publicKey:i})}catch(t){return c(T(t))}}function ir(e,r){try{V(e.challenge,"challenge");let t=x(e.challenge);return h({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:x(n.id),type:n.type,...n.transports&&{transports:n.transports}}))}},...r!==void 0&&{mediation:r}})}catch(t){return c(T(t))}}async function Ce(e,r,t){t.emit("start",{type:"start",operation:"register"});try{let n=e.externalUserId??e.external_user_id;if(!n||typeof n!="string"||n.trim()==="")return c(I("external_user_id","must be provided (use externalUserId or external_user_id)"));if(!k())return c(ee());let s=await r.startRegister({external_user_id:n.trim()});if(!s.ok)return t.emit("error",{type:"error",error:s.error}),c(s.error);let i=s.value,u=i.session_id,p=ge(i.challenge,e.authenticatorType);if(!p.ok)return t.emit("error",{type:"error",error:p.error}),c(p.error);let g=p.value;e.signal&&(g.signal=e.signal);let y;try{y=await navigator.credentials.create(g)}catch(R){let E=T(R);return t.emit("error",{type:"error",error:E}),c(E)}try{L(y,"create")}catch(R){let E=T(R);return t.emit("error",{type:"error",error:E}),c(E)}let m;try{m=H(y)}catch(R){let E=T(R);return t.emit("error",{type:"error",error:E}),c(E)}let d=await r.finishRegister({session_id:u,credential:m});if(!d.ok)return t.emit("error",{type:"error",error:d.error}),c(d.error);let _=d.value;return t.emit("success",{type:"success",operation:"register"}),h({success:!0,credential_id:_.credential_id,status:_.status,session_token:_.session_token,user:_.user})}catch(n){let s=T(n);return t.emit("error",{type:"error",error:s}),c(s)}}async function we(e,r,t){t.emit("start",{type:"start",operation:"authenticate"});try{let n=e.externalUserId??e.external_user_id;if(!n||typeof n!="string"||n.trim()==="")return c(I("external_user_id","must be provided (use externalUserId or external_user_id)"));if(!k())return c(ee());let s=await r.startAuth({external_user_id:n.trim()});if(!s.ok)return t.emit("error",{type:"error",error:s.error}),c(s.error);let i=s.value,u=i.session_id,p=ir(i.challenge,e.mediation);if(!p.ok)return t.emit("error",{type:"error",error:p.error}),c(p.error);let g=p.value;e.signal&&(g.signal=e.signal);let y;try{y=await navigator.credentials.get(g)}catch(R){let E=T(R);return t.emit("error",{type:"error",error:E}),c(E)}try{L(y,"get")}catch(R){let E=T(R);return t.emit("error",{type:"error",error:E}),c(E)}let m;try{m=Me(y)}catch(R){let E=T(R);return t.emit("error",{type:"error",error:E}),c(E)}let d=await r.finishAuth({session_id:u,credential:m});if(!d.ok)return t.emit("error",{type:"error",error:d.error}),c(d.error);let _=d.value;return t.emit("success",{type:"success",operation:"authenticate"}),h({authenticated:_.authenticated,session_token:_.session_token,user:_.user,signals:_.signals})}catch(n){let s=T(n);return t.emit("error",{type:"error",error:s}),c(s)}}var or=2e3,ar=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<ar;s++){await new Promise(g=>setTimeout(g,or));let i=await this.apiClient.getOnboardingStatus(n);if(!i.ok)return c(i.error);let u=i.value.status,p=i.value.onboarding_url;if(u==="pending_passkey"){let g=await this.apiClient.getOnboardingRegister(n);if(!g.ok)return c(g.error);let y=g.value;if(!y.challenge)return c(b("NOT_SUPPORTED","Onboarding requires user action - complete passkey registration at the provided onboarding_url",{onboarding_url:p}));let m=ge(y.challenge);if(!m.ok)return c(m.error);let d;try{d=await navigator.credentials.create(m.value)}catch(S){return c(T(S))}try{L(d,"create")}catch(S){return c(T(S))}let _;try{_=H(d)}catch(S){return c(T(S))}let R=await this.apiClient.registerOnboardingPasskey(n,{credential:_,challenge:y.challenge.challenge});return R.ok?await this.apiClient.completeOnboarding(n,{company_name:r.company_name}):c(R.error)}if(u==="completed")return await this.apiClient.completeOnboarding(n,{company_name:r.company_name})}return c(b("TIMEOUT","Onboarding timed out"))}};var $=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 xe="https://api.trymellonauth.com",De="https://api.trymellonauth.com/v1/telemetry";function Ne(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 me(e,r){return{event:e,latencyMs:r,ok:!0}}var X=class{apiClient;eventEmitter;telemetrySender;onboarding;constructor(r){let t=r.appId,n=r.publishableKey;if(!t||typeof t!="string"||t.trim()==="")throw I("appId","must be a non-empty string");if(!n||typeof n!="string"||n.trim()==="")throw I("publishableKey","must be a non-empty string");let s=r.apiBaseUrl??xe;Se(s,"apiBaseUrl");let i=r.timeoutMs??3e4;q(i,"timeoutMs",1e3,3e5),r.maxRetries!==void 0&&q(r.maxRetries,"maxRetries",0,10),r.retryDelayMs!==void 0&&q(r.retryDelayMs,"retryDelayMs",100,1e4);let u=r.maxRetries??3,p=r.retryDelayMs??1e3,g=new Y(i,u,p,r.logger),y={"X-App-Id":t.trim(),Authorization:`Bearer ${n.trim()}`};this.apiClient=new B(g,s,y),this.onboarding=new G(this.apiClient),this.eventEmitter=new $,r.enableTelemetry&&(this.telemetrySender=r.telemetrySender??Ne(r.telemetryEndpoint??De))}static isSupported(){return k()}async register(r){let t=Date.now(),n=await Ce(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(me("register",Date.now()-t)).catch(()=>{}),n}async authenticate(r){let t=Date.now(),n=await we(r,this.apiClient,this.eventEmitter);return n.ok&&this.telemetrySender&&this.telemetrySender.send(me("authenticate",Date.now()-t)).catch(()=>{}),n}async validateSession(r){return this.apiClient.validateSession(r)}async getStatus(){return Pe()}on(r,t){return this.eventEmitter.on(r,t)}version(){return"1.1.3"}fallback={email:{start:async r=>this.apiClient.startEmailFallback(r.userId),verify:async r=>this.apiClient.verifyEmailCode(r.userId,r.code)}}};var K=new D.InjectionToken("TRYMELLON_CONFIG"),Ue,fe;Ue=[(0,D.Injectable)({providedIn:"root"})];var M=class{config=(0,D.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 X(this.config)}return this._client}};fe=_e(null),M=Ae(fe,0,"TryMellonService",Ue,M),ve(fe,1,M);function yr(e){return{provide:K,useValue:e}}0&&(module.exports={TRYMELLON_CONFIG,TryMellonService,provideTryMellonConfig});
|
|
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});
|
|
3
3
|
//# sourceMappingURL=angular.cjs.map
|