@syndew/oluso-sdk 0.0.0-stage → 1.30.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/LICENSE +76 -0
- package/README.md +509 -2
- package/dist/auth/embed.global.js +210 -0
- package/dist/auth/embed.global.js.map +1 -0
- package/dist/auth/index.d.mts +535 -0
- package/dist/auth/index.d.ts +535 -0
- package/dist/auth/index.js +2118 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/index.mjs +2088 -0
- package/dist/auth/index.mjs.map +1 -0
- package/dist/embed.global.js +448 -0
- package/dist/embed.global.js.map +1 -0
- package/dist/index.d.mts +810 -0
- package/dist/index.d.ts +810 -0
- package/dist/index.js +2127 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2095 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +559 -0
- package/dist/react.d.ts +559 -0
- package/dist/react.js +1674 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +1642 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +72 -4
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
"use strict";var OlusoAuth=(()=>{var Z=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var Te=Object.getOwnPropertyNames;var Ae=Object.prototype.hasOwnProperty;var Re=(i,e)=>{for(var n in e)Z(i,n,{get:e[n],enumerable:!0})},Ue=(i,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Te(e))!Ae.call(i,s)&&s!==n&&Z(i,s,{get:()=>e[s],enumerable:!(o=Ee(e,s))||o.enumerable});return i};var Oe=i=>Ue(Z({},"__esModule",{value:!0}),i);var tt={};Re(tt,{close:()=>q,getUser:()=>Xe,hasPermission:()=>Ze,hasRole:()=>Qe,init:()=>Ve,logout:()=>et,onAuth:()=>Ge,open:()=>Ye,signInWithFedCM:()=>ke,signInWithPasskey:()=>ve});var z=class{constructor(e){this.listeners=new Map;if(!e.serverUrl)throw new Error("serverUrl is required");this.config={...e,serverUrl:e.serverUrl.replace(/\/$/,"")},this.fetchFn=e.fetch||globalThis.fetch.bind(globalThis)}async getJourney(e){return await this.request(`/api/public/journeys/${encodeURIComponent(e)}`)}async submit(e,n,o){try{let s=await this.request(`/api/public/journeys/${encodeURIComponent(e)}/submit`,{method:"POST",body:{data:n,metadata:{...o?.metadata,referrer:typeof document<"u"?document.referrer:void 0,userAgent:typeof navigator<"u"?navigator.userAgent:void 0},honeypot:o?.honeypot}});return this.emit({type:"submission:success",slug:e,data:s}),s}catch(s){throw this.emit({type:"submission:error",slug:e,error:s instanceof Error?s:new Error(String(s))}),s}}async startJourney(e,n){let o=await this.request(`/api/public/journeys/${encodeURIComponent(e)}/start`,{method:"POST",body:{data:n}});return this.emit({type:"journey:started",slug:o.slug,sessionId:o.sessionId,data:o}),o}async startAuthJourney(e,n,o){let s=await this.request(`/api/public/journeys/${encodeURIComponent(e)}/start`,{method:"POST",body:{data:o,clientId:n.clientId,codeChallenge:n.codeChallenge,codeChallengeMethod:"S256",scope:n.scope}});return this.emit({type:"journey:started",slug:s.slug,sessionId:s.sessionId,data:s}),s}async submitStep(e,n,o){let s=await this.request(`/api/public/journeys/sessions/${encodeURIComponent(e)}/step`,{method:"POST",body:{data:n,action:o}});return this.emit({type:s.completed?"journey:completed":s.success?"journey:step":"journey:error",slug:s.slug,sessionId:e,data:s}),s}async submitStepForm(e,n,o){o&&n.set("__journey_action",o);let s=await this.request(`/api/public/journeys/sessions/${encodeURIComponent(e)}/step`,{method:"POST",body:n});return this.emit({type:s.completed?"journey:completed":s.success?"journey:step":"journey:error",slug:s.slug,sessionId:e,data:s}),s}get serverUrl(){return this.config.serverUrl}async getSession(e){return this.request(`/api/public/journeys/sessions/${encodeURIComponent(e)}`)}getJourneyUrl(e,n){let o=new URLSearchParams;return this.config.tenant&&o.set("tenant",this.config.tenant),n?.redirectUri&&o.set("redirect_uri",n.redirectUri),n?.state&&o.set("state",n.state),`${this.config.serverUrl}/journey/start/${encodeURIComponent(e)}?${o}`}getEmbedUrl(e,n){let o=new URLSearchParams({embed:"true"});return this.config.tenant&&o.set("tenant",this.config.tenant),n?.theme&&o.set("theme",n.theme),n?.hideHeader&&o.set("hideHeader","true"),`${this.config.serverUrl}/journey/start/${encodeURIComponent(e)}?${o}`}on(e,n){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(n),()=>{this.listeners.get(e)?.delete(n)}}off(e,n){this.listeners.get(e)?.delete(n)}emit(e){this.listeners.get(e.type)?.forEach(n=>n(e)),this.listeners.get("*")?.forEach(n=>n(e))}async request(e,n){let o=`${this.config.serverUrl}${e}`,s=n?.method||"GET",a=typeof FormData<"u"&&n?.body instanceof FormData,g={};this.config.tenant&&(g["X-Tenant-ID"]=this.config.tenant),a||(g["Content-Type"]="application/json"),this.config.apiKey&&(g["X-API-Key"]=this.config.apiKey),this.config.headers&&Object.assign(g,await this.config.headers({method:s,url:o}));let m=await this.fetchFn(o,{method:s,headers:g,body:n?.body===void 0?void 0:a?n.body:JSON.stringify(n.body),credentials:"include"});if(!m.ok){let f=await m.json().catch(()=>({message:m.statusText}));throw new ee(f.message||`Request failed: ${m.status}`,m.status,f.code,f.errors)}return m.json()}},ee=class extends Error{constructor(n,o,s,a){super(n);this.status=o;this.code=s;this.fieldErrors=a;this.name="OlusoError"}};var Pe={eq:"eq",equals:"eq","==":"eq","=":"eq",ne:"ne",neq:"ne",notequals:"ne","!=":"ne",gt:"gt",">":"gt",greaterthan:"gt",gte:"gte",">=":"gte",greaterthanorequals:"gte",lt:"lt","<":"lt",lessthan:"lt",lte:"lte","<=":"lte",lessthanorequals:"lte",contains:"contains",notcontains:"not_contains","!contains":"not_contains",startswith:"starts_with",endswith:"ends_with",exists:"exists",notnull:"exists",isset:"exists",notexists:"not_exists",null:"not_exists",isnotset:"not_exists",empty:"empty",notempty:"not_empty",in:"in",notin:"not_in","!in":"not_in",regex:"regex",matches:"regex",true:"true",false:"false"};function Le(i){if(i)return Pe[i.trim().toLowerCase().replace(/_/g,"")]}var B=(i,e)=>i.localeCompare(e,void 0,{sensitivity:"accent"})===0;function K(i,e){if(e===void 0)return;let n=Number(i),o=Number(e);if(i.trim()!==""&&e.trim()!==""&&!Number.isNaN(n)&&!Number.isNaN(o))return n===o?0:n<o?-1:1;let s=Date.parse(i),a=Date.parse(e);return!Number.isNaN(s)&&!Number.isNaN(a)?s===a?0:s<a?-1:1:i.localeCompare(e,void 0,{sensitivity:"accent"})}function te(i,e,n){let o=i.toLowerCase(),s=(n??"").toLowerCase();switch(e){case"eq":return B(i,n??"");case"ne":return!B(i,n??"");case"gt":{let a=K(i,n);return a!==void 0&&a>0}case"gte":{let a=K(i,n);return a!==void 0&&a>=0}case"lt":{let a=K(i,n);return a!==void 0&&a<0}case"lte":{let a=K(i,n);return a!==void 0&&a<=0}case"contains":return o.includes(s);case"not_contains":return!o.includes(s);case"starts_with":return o.startsWith(s);case"ends_with":return o.endsWith(s);case"regex":if(!n)return!1;try{return new RegExp(n,"i").test(i)}catch{return!1}default:return!1}}function ae(i){if(!i||!i.trim())return[];let e=i.trim();if(e.startsWith("["))try{let n=JSON.parse(e);if(Array.isArray(n))return n.map(String)}catch{return[]}return e.split(",").map(n=>n.trim()).filter(Boolean)}var le=i=>i.toLowerCase()!=="false"&&i!=="0";function ue(i,e){let n=Le(i.operator),o=e.filter(a=>a!==""),s=()=>o.flatMap(a=>a.split(",").map(g=>g.trim()).filter(Boolean));switch(n){case"exists":case"not_empty":return o.length>0;case"not_exists":case"empty":return o.length===0;case"ne":return!o.some(a=>te(a,"eq",i.value));case"not_contains":return!o.some(a=>te(a,"contains",i.value));case"in":{let a=ae(i.value);return s().some(g=>a.some(m=>B(g,m)))}case"not_in":{let a=ae(i.value);return!s().some(g=>a.some(m=>B(g,m)))}case"true":return o.some(le);case"false":return!o.some(le);case void 0:return!1;default:return o.some(a=>te(a,n,i.value))}}var Ie=`
|
|
2
|
+
.oluso-journey {
|
|
3
|
+
--oluso-accent: #4f46e5;
|
|
4
|
+
--oluso-accent-contrast: #ffffff;
|
|
5
|
+
--oluso-fg: #111827;
|
|
6
|
+
--oluso-muted: #6b7280;
|
|
7
|
+
--oluso-bg: #ffffff;
|
|
8
|
+
--oluso-field-bg: #ffffff;
|
|
9
|
+
--oluso-border: #d1d5db;
|
|
10
|
+
--oluso-danger: #b91c1c;
|
|
11
|
+
--oluso-danger-bg: #fef2f2;
|
|
12
|
+
--oluso-notice-bg: #eff6ff;
|
|
13
|
+
--oluso-notice: #1d4ed8;
|
|
14
|
+
--oluso-radius: 8px;
|
|
15
|
+
--oluso-gap: 14px;
|
|
16
|
+
--oluso-font: inherit;
|
|
17
|
+
font-family: var(--oluso-font);
|
|
18
|
+
color: var(--oluso-fg);
|
|
19
|
+
font-size: 15px;
|
|
20
|
+
line-height: 1.5;
|
|
21
|
+
}
|
|
22
|
+
.oluso-journey[data-theme="dark"] {
|
|
23
|
+
--oluso-fg: #f3f4f6;
|
|
24
|
+
--oluso-muted: #9ca3af;
|
|
25
|
+
--oluso-bg: #111827;
|
|
26
|
+
--oluso-field-bg: #1f2937;
|
|
27
|
+
--oluso-border: #374151;
|
|
28
|
+
--oluso-danger: #fca5a5;
|
|
29
|
+
--oluso-danger-bg: rgba(185, 28, 28, 0.15);
|
|
30
|
+
--oluso-notice-bg: rgba(59, 130, 246, 0.15);
|
|
31
|
+
--oluso-notice: #93c5fd;
|
|
32
|
+
}
|
|
33
|
+
@media (prefers-color-scheme: dark) {
|
|
34
|
+
.oluso-journey[data-theme="auto"] {
|
|
35
|
+
--oluso-fg: #f3f4f6;
|
|
36
|
+
--oluso-muted: #9ca3af;
|
|
37
|
+
--oluso-bg: #111827;
|
|
38
|
+
--oluso-field-bg: #1f2937;
|
|
39
|
+
--oluso-border: #374151;
|
|
40
|
+
--oluso-danger: #fca5a5;
|
|
41
|
+
--oluso-danger-bg: rgba(185, 28, 28, 0.15);
|
|
42
|
+
--oluso-notice-bg: rgba(59, 130, 246, 0.15);
|
|
43
|
+
--oluso-notice: #93c5fd;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
.oluso-journey *, .oluso-journey *::before, .oluso-journey *::after { box-sizing: border-box; }
|
|
47
|
+
.oluso-journey__form { display: flex; flex-direction: column; gap: var(--oluso-gap); margin: 0; }
|
|
48
|
+
.oluso-journey__title { font-size: 1.25em; font-weight: 600; margin: 0; }
|
|
49
|
+
.oluso-journey__description { color: var(--oluso-muted); margin: 0; white-space: pre-line; }
|
|
50
|
+
.oluso-journey__alert { border-radius: var(--oluso-radius); padding: 10px 12px; margin: 0; }
|
|
51
|
+
.oluso-journey__alert--error { background: var(--oluso-danger-bg); color: var(--oluso-danger); }
|
|
52
|
+
.oluso-journey__alert--notice { background: var(--oluso-notice-bg); color: var(--oluso-notice); }
|
|
53
|
+
.oluso-journey__group { display: flex; flex-direction: column; gap: var(--oluso-gap); border: 0; margin: 0; padding: 0; }
|
|
54
|
+
.oluso-journey__field { display: flex; flex-direction: column; gap: 6px; }
|
|
55
|
+
.oluso-journey__field[hidden] { display: none; }
|
|
56
|
+
.oluso-journey__label { font-weight: 500; }
|
|
57
|
+
.oluso-journey__required { color: var(--oluso-danger); margin-left: 2px; }
|
|
58
|
+
.oluso-journey__input, .oluso-journey__select, .oluso-journey__textarea {
|
|
59
|
+
width: 100%; font: inherit; color: var(--oluso-fg); background: var(--oluso-field-bg);
|
|
60
|
+
border: 1px solid var(--oluso-border); border-radius: var(--oluso-radius); padding: 9px 11px; min-height: 40px;
|
|
61
|
+
}
|
|
62
|
+
.oluso-journey__input:focus, .oluso-journey__select:focus, .oluso-journey__textarea:focus {
|
|
63
|
+
outline: 2px solid var(--oluso-accent); outline-offset: 1px; border-color: transparent;
|
|
64
|
+
}
|
|
65
|
+
.oluso-journey__input[aria-invalid="true"], .oluso-journey__select[aria-invalid="true"], .oluso-journey__textarea[aria-invalid="true"] {
|
|
66
|
+
border-color: var(--oluso-danger);
|
|
67
|
+
}
|
|
68
|
+
.oluso-journey__input--otp { letter-spacing: 0.4em; font-variant-numeric: tabular-nums; text-align: center; font-size: 1.2em; }
|
|
69
|
+
.oluso-journey__phone { display: flex; gap: 8px; }
|
|
70
|
+
.oluso-journey__phone .oluso-journey__select { width: auto; max-width: 45%; }
|
|
71
|
+
.oluso-journey__choices { display: flex; flex-direction: column; gap: 8px; }
|
|
72
|
+
.oluso-journey__choice { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
|
|
73
|
+
.oluso-journey__choice input { margin-top: 3px; accent-color: var(--oluso-accent); }
|
|
74
|
+
.oluso-journey__choice-description { display: block; color: var(--oluso-muted); font-size: 0.9em; }
|
|
75
|
+
.oluso-journey__help, .oluso-journey__hint { color: var(--oluso-muted); font-size: 0.875em; margin: 0; }
|
|
76
|
+
.oluso-journey__error { color: var(--oluso-danger); font-size: 0.875em; margin: 0; }
|
|
77
|
+
.oluso-journey__content { margin: 0; white-space: pre-line; }
|
|
78
|
+
.oluso-journey__actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
|
|
79
|
+
.oluso-journey__button {
|
|
80
|
+
font: inherit; font-weight: 500; border-radius: var(--oluso-radius); padding: 9px 16px; min-height: 40px; cursor: pointer;
|
|
81
|
+
border: 1px solid var(--oluso-border); background: var(--oluso-field-bg); color: var(--oluso-fg);
|
|
82
|
+
}
|
|
83
|
+
.oluso-journey__button--primary { background: var(--oluso-accent); color: var(--oluso-accent-contrast); border-color: var(--oluso-accent); }
|
|
84
|
+
.oluso-journey__button--primary:only-child, .oluso-journey__actions--stacked .oluso-journey__button--primary { flex: 1 1 auto; }
|
|
85
|
+
.oluso-journey__button--link { background: none; border: 0; color: var(--oluso-accent); padding: 4px 0; min-height: 0; }
|
|
86
|
+
.oluso-journey__button--cancel { background: none; }
|
|
87
|
+
.oluso-journey__button:disabled { opacity: 0.6; cursor: progress; }
|
|
88
|
+
.oluso-journey__enter { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
|
|
89
|
+
.oluso-journey__action-line { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; margin: 0; }
|
|
90
|
+
.oluso-journey__links { display: flex; flex-wrap: wrap; gap: 12px; font-size: 0.9em; }
|
|
91
|
+
.oluso-journey__links a { color: var(--oluso-accent); }
|
|
92
|
+
.oluso-journey__qr { display: flex; flex-direction: column; align-items: center; gap: 8px; }
|
|
93
|
+
.oluso-journey__qr img { width: 180px; height: 180px; background: #fff; padding: 8px; border-radius: var(--oluso-radius); }
|
|
94
|
+
.oluso-journey__code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; word-break: break-all; }
|
|
95
|
+
.oluso-journey__codes { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin: 0; padding: 0; list-style: none; }
|
|
96
|
+
.oluso-journey__codes li { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; padding: 6px 8px; border: 1px solid var(--oluso-border); border-radius: 6px; text-align: center; }
|
|
97
|
+
.oluso-journey__status { color: var(--oluso-muted); text-align: center; padding: 16px 0; }
|
|
98
|
+
.oluso-journey__done { text-align: center; padding: 8px 0; }
|
|
99
|
+
`,ce=!1;function de(){if(ce||typeof document>"u")return;let i=document.createElement("style");i.setAttribute("data-oluso-journey",""),i.textContent=Ie,document.head.appendChild(i),ce=!0}function W(i){let e=i.replace(/-/g,"+").replace(/_/g,"/"),n=e+"=".repeat((4-e.length%4)%4),o=atob(n),s=new Uint8Array(o.length);for(let a=0;a<o.length;a++)s[a]=o.charCodeAt(a);return s.buffer}function M(i){if(!i)return null;let e=new Uint8Array(i),n="";for(let o=0;o<e.length;o++)n+=String.fromCharCode(e[o]);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function pe(i){if(Array.isArray(i))return i.map(e=>({type:e.type??"public-key",id:W(String(e.id)),transports:e.transports}))}function Je(i){return{...i,challenge:W(String(i.challenge)),allowCredentials:pe(i.allowCredentials)}}function Me(i){let e=i.user??{};return{...i,challenge:W(String(i.challenge)),user:{...e,id:W(String(e.id))},excludeCredentials:pe(i.excludeCredentials)}}async function he(i){let e=await navigator.credentials.get({publicKey:Je(i)});if(!e)throw new Error("No passkey was chosen");let n=e.response;return JSON.stringify({id:e.id,rawId:M(e.rawId),type:e.type,response:{clientDataJSON:M(n.clientDataJSON),authenticatorData:M(n.authenticatorData),signature:M(n.signature),userHandle:M(n.userHandle)},authenticatorAttachment:e.authenticatorAttachment??null})}async function ge(i){let e=await navigator.credentials.create({publicKey:Me(i)});if(!e)throw new Error("No passkey was created");let n=e.response;return JSON.stringify({id:e.id,rawId:M(e.rawId),type:e.type,response:{clientDataJSON:M(n.clientDataJSON),attestationObject:M(n.attestationObject),transports:typeof n.getTransports=="function"?n.getTransports():void 0},authenticatorAttachment:e.authenticatorAttachment??null})}var $e={loading:"Loading\u2026",completed:"All done. Thank you.",failed:"Something went wrong. Please try again.",expired:"This session has expired. Please start again.",restart:"Start again",takePhoto:"Take a photo",copy:"Copy",copied:"Copied",passkey:"Use your passkey",retry:"Try again",waiting:"Waiting\u2026",unavailable:"This step can\u2019t be shown here."};function d(i,e,n){let o=document.createElement(i);return e&&(o.className=e),n!==void 0&&(o.textContent=n),o}var Fe=0;function fe(i,e){let n={...$e,...e.labels},o=e.client,s=`oluso-j${++Fe}`,a,g=!1,m=[];e.unstyled||de();let f=d("div","oluso-journey");f.setAttribute("data-theme",e.theme??"auto"),i.appendChild(f);let x=()=>{m.forEach(t=>window.clearInterval(t)),m=[]},L=t=>{f.replaceChildren(d("p","oluso-journey__status",t))},C=t=>{let c=t instanceof Error?t:new Error(String(t));return e.onError?.(c,a),c},U=()=>!!(e.slug||e.start),P=async()=>{x(),L(n.loading);try{let t=e.start?await e.start():e.slug?await o.startJourney(e.slug,e.data):e.session;if(!t)throw new Error("mountJourney needs a slug, a session or a start function");await w(t)}catch(t){F(C(t).message)}},w=async t=>{if(!g){if(x(),a=t,e.onStep?.(t),t.completed){if(t.redirectUrl){await e.onComplete?.(t),I(t.redirectUrl,t);return}if(e.showCompletion!==!1){let c=d("div","oluso-journey__done");c.appendChild(d("p","oluso-journey__content",t.message||n.completed)),f.replaceChildren(c)}else f.replaceChildren();await e.onComplete?.(t);return}if(t.status!=="in_progress"){let c=t.status==="expired"?n.expired:t.errorDescription||n.failed;C(new Error(c)),F(c);return}if(t.redirectUrl){I(t.redirectUrl,t);return}t.step?.form?A(t.step.form):t.step?.html?Se(t.step.html):F(n.unavailable)}},I=(t,c)=>{e.onRedirect?e.onRedirect(t,c):window.location.assign(t)},F=t=>{let c=d("div","oluso-journey__form");if(c.appendChild(d("p","oluso-journey__alert oluso-journey__alert--error",t)),U()){let l=d("button","oluso-journey__button oluso-journey__button--primary",n.restart);l.type="button",l.addEventListener("click",()=>{P()});let y=d("div","oluso-journey__actions");y.appendChild(l),c.appendChild(y)}f.replaceChildren(c)},$=async(t,c)=>{if(!a)return;let l=await o.submitStepForm(a.sessionId,t,c);await w(l)},T=(t,c)=>{t.setAttribute("aria-busy",String(c)),t.querySelectorAll("button").forEach(l=>l.disabled=c)},H=async(t,c,l)=>{let y=c?.postsFields===!1?new FormData:new FormData(t);if(c?.name&&y.append(c.name,c.value??""),c?.values)for(let[_,u]of Object.entries(c.values))y.append(_,u);if(l)for(let[_,u]of Object.entries(l))y.set(_,u);T(t,!0);try{await $(y)}catch(_){T(t,!1);let u=C(_).message,r=t.querySelector("[data-oluso-request-error]");r||(r=d("p","oluso-journey__alert oluso-journey__alert--error"),r.setAttribute("data-oluso-request-error",""),r.setAttribute("role","alert"),t.prepend(r)),r.textContent=u}},A=t=>{let c=d("form","oluso-journey__form");if(t.title&&c.appendChild(d("h2","oluso-journey__title",t.title)),t.description&&c.appendChild(d("p","oluso-journey__description",t.description)),t.error){let u=d("p","oluso-journey__alert oluso-journey__alert--error",t.error);u.setAttribute("role","alert"),c.appendChild(u)}if(t.notice){let u=d("p","oluso-journey__alert oluso-journey__alert--notice",t.notice);u.setAttribute("role","status"),c.appendChild(u)}let l=[];for(let u of t.fields){let r=Q(u);r&&(c.appendChild(r),(u.showWhen||u.showWhenAll?.length)&&l.push({field:u,wrapper:r}))}if(t.widget){let u=xe(t.widget,c);u&&c.appendChild(u)}if(t.links.length>0){let u=d("div","oluso-journey__links");for(let r of t.links){let h=d("a",void 0,r.label);h.href=r.url,h.target="_blank",h.rel="noopener noreferrer",u.appendChild(h)}c.appendChild(u)}if(t.actions.length>0){let u=d("div","oluso-journey__actions"),r=t.actions.findIndex(p=>p.kind==="primary");if(r>=0){let p=d("button","oluso-journey__enter");p.type="submit",p.tabIndex=-1,p.setAttribute("aria-hidden","true"),p.dataset.olusoAction=String(r),c.prepend(p)}let h=[];t.actions.forEach((p,b)=>{let v=d("button",`oluso-journey__button oluso-journey__button--${p.kind}`,p.label);if(v.type="submit",v.formNoValidate=p.skipValidation||p.postsFields===!1,v.dataset.olusoAction=String(b),p.description){let k=d("p","oluso-journey__action-line");k.appendChild(d("span","oluso-journey__help",p.description)),k.appendChild(v),h.push(k)}else u.appendChild(v)}),u.childElementCount>0&&c.appendChild(u),h.forEach(p=>c.appendChild(p))}let y=()=>{for(let{field:u,wrapper:r}of l){let p=[...u.showWhen?[u.showWhen]:[],...u.showWhenAll??[]].every(b=>ue(b,qe(c.elements.namedItem(b.field))));r.hidden=!p,r.querySelectorAll("input, select, textarea").forEach(b=>{b.disabled=!p||b.dataset.olusoReadonly==="true"})}};c.addEventListener("input",u=>{y();let h=u.target.closest(".oluso-journey__field");h?.querySelectorAll('[aria-invalid="true"]').forEach(p=>p.removeAttribute("aria-invalid")),h?.querySelector(".oluso-journey__error")?.remove()}),c.addEventListener("change",y),y(),c.addEventListener("submit",u=>{u.preventDefault();let r=u.submitter,h=r?.dataset.olusoAction,p=h!==void 0?t.actions[Number(h)]:t.actions.find(b=>b.kind==="primary");if(p?.confirm&&r&&r.dataset.olusoConfirming!=="true"){r.dataset.olusoConfirming="true",r.textContent=p.confirm,r.setAttribute("aria-live","polite");return}H(c,p)}),f.replaceChildren(c),(c.querySelector("[autofocus]")??c.querySelector("input:not([type=hidden]):not([disabled]), select, textarea"))?.focus({preventScroll:!0})},Q=t=>{let c=`${s}-${t.name}`;if(t.type==="hidden"){let r=d("input");return r.type="hidden",r.name=t.name,r.value=t.value??"",r}let l=d("div","oluso-journey__field");if(t.group&&(l.dataset.group=t.group),t.type==="content")return t.label&&l.appendChild(d("p","oluso-journey__label",t.label)),l.appendChild(d("p","oluso-journey__content",t.value??"")),l;let y=()=>{if(!t.label)return;let r=d("label","oluso-journey__label",t.label);if(r.htmlFor=c,t.required){let h=d("span","oluso-journey__required","*");h.setAttribute("aria-hidden","true"),r.appendChild(h)}l.appendChild(r)},_=[],u=r=>{r.id=c,r.name=t.name,r.required=t.required,t.readOnly&&(r instanceof HTMLSelectElement?r.disabled=!0:r.readOnly=!0,r.dataset.olusoReadonly=String(r instanceof HTMLSelectElement)),t.autofocus&&(r.autofocus=!0),t.autocomplete&&r.setAttribute("autocomplete",t.autocomplete),t.error&&r.setAttribute("aria-invalid","true")};switch(t.type){case"textarea":{y();let r=d("textarea","oluso-journey__textarea");u(r),r.value=t.value??"",t.placeholder&&(r.placeholder=t.placeholder),t.rows&&(r.rows=t.rows),t.minLength&&(r.minLength=t.minLength),t.maxLength&&(r.maxLength=t.maxLength),l.appendChild(r);break}case"select":{y();let r=d("select","oluso-journey__select");u(r);let h=d("option",void 0,t.placeholder??"");h.value="",r.appendChild(h);for(let p of t.options??[]){let b=d("option",void 0,p.label);b.value=p.value,b.disabled=p.disabled,b.selected=p.value===t.value,r.appendChild(b)}l.appendChild(r);break}case"radio":{let r=d("fieldset","oluso-journey__group");if(t.label){let p=d("legend","oluso-journey__label",t.label);t.required&&p.appendChild(d("span","oluso-journey__required","*")),r.appendChild(p)}let h=d("div","oluso-journey__choices");(t.options??[]).forEach((p,b)=>{let v=d("label","oluso-journey__choice"),k=d("input");k.type="radio",k.name=t.name,k.value=p.value,k.id=`${c}-${b}`,k.required=t.required,k.disabled=p.disabled||t.readOnly,k.checked=p.value===t.value;let S=d("span",void 0,p.label);p.description&&S.appendChild(d("span","oluso-journey__choice-description",p.description)),v.append(k,S),h.appendChild(v)}),r.appendChild(h),l.appendChild(r);break}case"checkbox":{t.placeholder&&y();let r=d("label","oluso-journey__choice"),h=d("input");h.type="checkbox",h.value="true",u(h),h.checked=t.value==="true",t.readOnly&&(h.setAttribute("aria-readonly","true"),h.addEventListener("click",b=>b.preventDefault()));let p=d("span",void 0,t.placeholder??t.label??"");!t.placeholder&&t.required&&p.appendChild(d("span","oluso-journey__required","*")),r.append(h,p),l.appendChild(r);break}case"file":{y();let r=d("input","oluso-journey__input");if(r.type="file",u(r),r.readOnly=!1,r.disabled=t.readOnly,t.accept&&(r.accept=t.accept),r.multiple=(t.maxFiles??1)>1,r.required=t.required&&!t.capture,l.appendChild(r),t.capture&&!t.readOnly){let h=d("label","oluso-journey__hint",n.takePhoto);h.htmlFor=`${c}-camera`;let p=d("input","oluso-journey__input");p.type="file",p.id=`${c}-camera`,p.name=t.name,p.accept="image/*",p.setAttribute("capture",t.capture),l.append(h,p)}break}case"tel":{if(y(),t.countries&&t.countries.length>0){let r=d("div","oluso-journey__phone"),h=d("select","oluso-journey__select");h.name=`${t.name}__country`,h.setAttribute("aria-label",t.label??t.name),h.disabled=t.readOnly;for(let b of t.countries){let v=d("option",void 0,`${b.flag?b.flag+" ":""}${b.name} (${b.dialCode})`);v.value=b.code,v.selected=b.code===t.country,h.appendChild(v)}let p=d("input","oluso-journey__input");p.type="tel",p.inputMode="tel",u(p),p.value=t.value??"",t.placeholder&&(p.placeholder=t.placeholder),r.append(h,p),l.appendChild(r)}else{let r=ie(t,"tel");u(r),l.appendChild(r)}break}case"otp":{y();let r=d("input","oluso-journey__input oluso-journey__input--otp");r.type="text",r.inputMode="numeric",u(r),r.setAttribute("autocomplete",t.autocomplete??"one-time-code"),t.maxLength&&(r.maxLength=t.maxLength,r.minLength=t.minLength??t.maxLength),r.pattern=t.pattern??"[0-9]*",r.value=t.value??"",l.appendChild(r);break}default:{y();let h=ie(t,["text","email","password","number","date","url","tel"].includes(t.type)?t.type:"text");u(h),l.appendChild(h)}}if(t.description){let r=d("p","oluso-journey__help",t.description);r.id=`${c}-help`,_.push(r.id),l.appendChild(r)}if(t.hint){let r=d("p","oluso-journey__hint",t.hint);r.id=`${c}-hint`,_.push(r.id),l.appendChild(r)}if(t.error){let r=d("p","oluso-journey__error",t.error);r.id=`${c}-error`,_.push(r.id),l.appendChild(r)}return _.length>0&&Array.from(l.querySelectorAll("[id]")).find(r=>r.id===c)?.setAttribute("aria-describedby",_.join(" ")),l},ie=(t,c)=>{let l=d("input","oluso-journey__input");return l.type=c,l.value=t.value??"",t.placeholder&&(l.placeholder=t.placeholder),t.pattern&&(l.pattern=t.pattern),t.patternError&&(l.title=t.patternError,l.addEventListener("invalid",()=>{l.validity.patternMismatch&&l.setCustomValidity(t.patternError)}),l.addEventListener("input",()=>l.setCustomValidity(""))),t.minLength&&(l.minLength=t.minLength),t.maxLength&&(l.maxLength=t.maxLength),t.min&&(l.min=t.min),t.max&&(l.max=t.max),c==="number"&&(l.step="any"),l},xe=(t,c)=>{let l=t.data??{},y=d("div","oluso-journey__widget"),_=u=>{if(!t.resultField)return;let r=Array.from(c.querySelectorAll("input[type=hidden]")).find(h=>h.name===t.resultField)??null;r||(r=d("input"),r.type="hidden",r.name=t.resultField,c.appendChild(r)),r.value=u};switch(t.type){case"webauthn_get":case"webauthn_create":{let u=d("button","oluso-journey__button oluso-journey__button--primary",t.submit?.label??n.passkey);u.type="button";let r=async()=>{u.disabled=!0;try{let h=await Ce(l),p=h.publicKey,b=h.extra,v=t.type==="webauthn_get"?await he(p):await ge(p);_(v);let k=l.credentialName;if(k?.field){let S=JSON.parse(v).authenticatorAttachment,J=S==="platform"?k.platform:S==="cross-platform"?k.crossPlatform:k.other;(b??(b={}))[k.field]=J??""}await H(c,t.submit,b)}catch(h){u.disabled=!1,u.textContent=n.retry,e.onError?.(h instanceof Error?h:new Error(String(h)),a)}};return u.addEventListener("click",()=>{r()}),y.appendChild(u),typeof PublicKeyCredential<"u"&&queueMicrotask(()=>{r()}),y}case"verification_connect":{let u=l.options??{},r=typeof l.referenceOption=="string"?u[l.referenceOption]:void 0,h=typeof l.referenceField=="string"?l.referenceField:"reference_id",p=async S=>{let J=new FormData;S&&J.set(h,r==null?"":String(r)),T(c,!0);try{await $(J,"callback")}catch(je){T(c,!1),C(je)}},b=async()=>{await He(String(l.scriptUrl));let S=window[typeof l.global=="string"?l.global:"Connect"];if(!S)throw new Error("The verification widget could not be loaded");let J=new S({...u,onSuccess:()=>{p(!0)},onError:()=>{p(!1)},onClose:()=>{}});return J.setup?.(),J.open(),J},v,k=()=>{if(v){v.then(S=>S.open());return}v=b(),v.catch(S=>{v=void 0,C(S)})};if(t.submit){let S=d("button",`oluso-journey__button oluso-journey__button--${t.submit.kind}`,t.submit.label);S.type="button",S.addEventListener("click",k),y.appendChild(S)}return k(),y}case"captcha":{let u=d("div","oluso-journey__captcha");return y.appendChild(u),De(u,l,r=>{_(r),t.submit&&H(c,t.submit)}).catch(r=>e.onError?.(r instanceof Error?r:new Error(String(r)),a)),y}case"qr":{let u=d("div","oluso-journey__qr");if(typeof l.image=="string"){let r=d("img");r.src=l.image,r.alt="",u.appendChild(r)}return typeof l.secret=="string"?(typeof l.secretLabel=="string"&&u.appendChild(d("span","oluso-journey__help",l.secretLabel)),u.appendChild(d("code","oluso-journey__code",l.secret))):typeof l.value=="string"&&typeof l.image!="string"&&u.appendChild(d("code","oluso-journey__code",l.value)),y.appendChild(u),y}case"codes":{let u=Array.isArray(l.codes)?l.codes.map(String):[],r=d("ul","oluso-journey__codes");u.forEach(p=>r.appendChild(d("li",void 0,p)));let h=d("button","oluso-journey__button",n.copy);return h.type="button",h.addEventListener("click",()=>{navigator.clipboard?.writeText(u.join(`
|
|
100
|
+
`)).then(()=>h.textContent=n.copied)}),y.append(r,h),y}case"poll":{let u=Math.max(2,Number(l.intervalSeconds)||5),r=Number(l.maxSeconds)>0?Date.now()+Number(l.maxSeconds)*1e3:1/0,h=a?.currentStep;return m.push(window.setInterval(()=>{if(Date.now()>r){x();return}!a||document.hidden||o.getSession(a.sessionId).then(async p=>{(p.status!=="in_progress"||p.currentStep!==h)&&(x(),await $(new FormData,"init"))}).catch(()=>{})},u*1e3)),null}default:return null}},Ce=async t=>{if(t.publicKey)return{publicKey:t.publicKey,extra:void 0};let c=String(t.optionsUrl),l=/^https?:/i.test(c)?c:`${o.serverUrl}${c.startsWith("/")?"":"/"}${c}`,y=String(t.optionsMethod??"POST").toUpperCase(),_=await fetch(l,{method:y,headers:{"Content-Type":"application/json"},body:y==="GET"?void 0:JSON.stringify(t.optionsBody??{}),credentials:"include"});if(!_.ok)throw new Error(n.failed);let u=await _.json(),r={};return typeof t.idProperty=="string"&&typeof t.idField=="string"&&u[t.idProperty]!=null&&(r[t.idField]=String(u[t.idProperty])),{publicKey:u.options??u,extra:r}},Se=t=>{let c=d("div","oluso-journey__html");c.innerHTML=t,c.querySelectorAll("script").forEach(l=>l.remove()),c.addEventListener("submit",l=>{let y=l.target;l.preventDefault();let _=l.submitter,u=new FormData(y);_?.name&&u.append(_.name,_.value),u.delete("__RequestVerificationToken"),T(y,!0),$(u).catch(r=>{T(y,!1),C(r)})}),f.replaceChildren(c)};return e.session?w(e.session):P(),{get session(){return a},restart:P,destroy(){g=!0,x(),f.remove()}}}function qe(i){return i?(i instanceof RadioNodeList?Array.from(i):[i]).flatMap(n=>{let o=n;return o.disabled?[]:o.type==="checkbox"||o.type==="radio"?o.checked?[o.value]:[]:o instanceof HTMLSelectElement&&o.multiple?Array.from(o.selectedOptions).map(s=>s.value):[o.value]}):[]}var ne=new Map;function He(i){let e=ne.get(i);return e||(e=new Promise((n,o)=>{let s=document.createElement("script");s.src=i,s.async=!0,s.onload=()=>n(),s.onerror=()=>{ne.delete(i),o(new Error("A script the step needs could not be loaded"))},document.head.appendChild(s)}),ne.set(i,e)),e}var Ne={recaptcha:{src:"https://www.google.com/recaptcha/api.js?render=explicit&onload=",global:"grecaptcha"},hcaptcha:{src:"https://js.hcaptcha.com/1/api.js?render=explicit&onload=",global:"hcaptcha"},turnstile:{src:"https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit&onload=",global:"turnstile"}};async function De(i,e,n){let o=String(e.provider??"recaptcha").toLowerCase(),s=Ne[o];if(!s)throw new Error(`Captcha provider '${o}' isn't supported`);let a=window;if(!a[s.global]){let f=`__olusoCaptcha${Date.now()}`;await new Promise((x,L)=>{a[f]=()=>x();let C=document.createElement("script");C.src=s.src+f+(e.language?`&hl=${encodeURIComponent(String(e.language))}`:""),C.async=!0,C.onerror=()=>L(new Error("The captcha could not be loaded")),document.head.appendChild(C)})}let g=a[s.global],m=String(e.siteKey??"");if(o==="recaptcha"&&e.version==="v3"&&g.execute){g.ready?.(()=>{g.execute(m,{action:String(e.action??"submit")}).then(n)});return}g.render(i,{sitekey:m,theme:e.theme,size:e.size,action:e.action,callback:f=>n(f)})}var oe="oluso_auth_tokens",re=class{constructor(){this.tokens=null}getTokens(){return this.tokens&&Date.now()/1e3>=this.tokens.expiresAt&&(this.tokens=null),this.tokens}setTokens(e){this.tokens=e}clear(){this.tokens=null}},se=class{constructor(e){this.store=e==="localStorage"?localStorage:sessionStorage}getTokens(){try{let e=this.store.getItem(oe);if(!e)return null;let n=JSON.parse(e);return Date.now()/1e3>=n.expiresAt?(this.clear(),null):n}catch{return null}}setTokens(e){this.store.setItem(oe,JSON.stringify(e))}clear(){this.store.removeItem(oe)}};function ye(i){return i==="memory"?new re:new se(i)}var V=class{constructor(e){this.user=null;this.resolvedEndpoints=null;this.discoveryPromise=null;this.journeyVerifiers=new Map;if(!e.serverUrl||!e.tenant||!e.clientId)throw new Error("serverUrl, tenant, and clientId are required");this.config={scopes:"openid profile email",signInJourney:"signin",signUpJourney:"signup",passwordResetJourney:"password-reset",storage:"memory",...e,serverUrl:e.serverUrl.replace(/\/$/,"")},this.storage=ye(this.config.storage);let n=this.storage.getTokens();n&&(this.user=this.parseIdToken(n.idToken))}async signIn(e){return e?this.executeJourney(this.config.signInJourney,e):this.openAuthModal("signin")}async signUp(e){return e?this.executeJourney(this.config.signUpJourney,e):this.openAuthModal("signup")}async signInWithPasskey(e){if(!window.PublicKeyCredential)return{success:!1,error:"WebAuthn is not supported in this browser"};let{verifier:n,challenge:o}=await this.generatePkce(),s=`${this.config.serverUrl}/connect/webauthn/assertion-options`,a=await fetch(s,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({clientId:this.config.clientId,username:e?.username,scope:this.config.scopes,codeChallenge:o,codeChallengeMethod:"S256"})});if(!a.ok){let w=await a.json().catch(()=>({error_description:"Failed to get passkey options"}));return{success:!1,error:w.error_description||w.error}}let g=await a.json(),m={challenge:this.base64UrlDecode(g.challenge),timeout:g.timeout,rpId:g.rpId,userVerification:g.userVerification||"preferred",allowCredentials:g.allowCredentials?.map(w=>({type:w.type,id:this.base64UrlDecode(w.id),transports:w.transports}))},f;try{let w={publicKey:m,signal:e?.signal};e?.conditional&&(w.mediation="conditional"),f=await navigator.credentials.get(w)}catch(w){let I=w instanceof Error?w.message:"Passkey request failed";return w instanceof DOMException&&w.name==="AbortError"?{success:!1,error:"cancelled"}:w instanceof DOMException&&w.name==="NotAllowedError"?{success:!1,error:"cancelled"}:{success:!1,error:I}}if(!f)return{success:!1,error:"No credential returned"};let x=f.response,L=JSON.stringify({id:f.id,rawId:this.base64UrlEncode(new Uint8Array(f.rawId)),type:f.type,response:{clientDataJSON:this.base64UrlEncode(new Uint8Array(x.clientDataJSON)),authenticatorData:this.base64UrlEncode(new Uint8Array(x.authenticatorData)),signature:this.base64UrlEncode(new Uint8Array(x.signature)),userHandle:x.userHandle?this.base64UrlEncode(new Uint8Array(x.userHandle)):null}}),C=`${this.config.serverUrl}/connect/webauthn/assertion`,U=await fetch(C,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({clientId:this.config.clientId,assertionId:g.assertionId,assertionResponse:L,codeChallenge:o,codeChallengeMethod:"S256",scope:this.config.scopes})});if(!U.ok){let w=await U.json().catch(()=>({error_description:"Passkey verification failed"}));return{success:!1,error:w.error_description||w.error}}let{code:P}=await U.json();return this.exchangeCodeForTokens(P,n,"postmessage")}async signInWithFedCM(e){if(!("IdentityCredential"in window))return{success:!1,error:"FedCM is not supported in this browser"};let{verifier:n,challenge:o}=await this.generatePkce();try{let s=await navigator.credentials.get({identity:{providers:[{configURL:`${this.config.serverUrl}/fedcm/config.json`,clientId:this.config.clientId,nonce:e?.nonce,loginHint:e?.loginHint,params:{code_challenge:o,code_challenge_method:"S256",scope:this.config.scopes}}]},mediation:e?.autoReauth?"optional":"required"});return s?.token?this.exchangeCodeForTokens(s.token,n,"fedcm"):{success:!1,error:"No credential returned from FedCM"}}catch(s){return s instanceof DOMException&&s.name==="AbortError"?{success:!1,error:"cancelled"}:s instanceof DOMException&&s.name==="NetworkError"?{success:!1,error:"FedCM network error \u2014 user may not be signed in to the identity provider"}:{success:!1,error:s instanceof Error?s.message:"FedCM request failed"}}}mountSignIn(e,n={}){let o=new z({serverUrl:this.config.serverUrl,tenant:this.config.tenant,apiKey:this.config.apiKey}),s="";return fe(e,{client:o,theme:n.theme,unstyled:n.unstyled,labels:n.labels,showCompletion:!1,onError:n.onError,onRedirect:n.onRedirect,start:async()=>{let a=await this.generatePkce();return s=a.verifier,o.startAuthJourney(n.journey??this.config.signInJourney,{clientId:this.config.clientId,codeChallenge:a.challenge,scope:this.config.scopes})},onComplete:async a=>{let g=a.code?await this.exchangeCodeForTokens(a.code,s,"postmessage"):{success:!1,error:a.errorDescription||a.error||"Authentication failed",code:a.error};n.onSignedIn?.(g)}})}async continueStep(e,n){let o=this.journeyVerifiers.get(e);if(!o)return{success:!1,error:"This journey was not started by this client",code:"invalid_session"};let s=`${this.config.serverUrl}/api/public/journeys/sessions/${encodeURIComponent(e)}/step`,a=await fetch(s,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({data:n}),credentials:"include"});if(!a.ok){let g=await a.json().catch(()=>({message:"Step failed"}));return{success:!1,error:g.error_description||g.message,code:g.error||g.code}}return this.handleJourneyResult(await a.json(),o)}async getJourneyStep(e){let n=`${this.config.serverUrl}/api/public/journeys/${encodeURIComponent(e)}`,o=await fetch(n,{headers:this.buildHeaders(),credentials:"include"});if(!o.ok)return null;let s=await o.json();return{step:"initial",fields:s.fields||[],title:s.ui?.title||s.name,description:s.description}}async loginWithRedirect(e){let{verifier:n,challenge:o}=await this.generatePkce();sessionStorage.setItem("oluso_pkce_verifier",n),e?.state&&sessionStorage.setItem("oluso_auth_state",e.state);let s=await this.getEndpoints(),a=new URLSearchParams({response_type:"code",client_id:this.config.clientId,redirect_uri:this.config.redirectUri||window.location.origin+"/callback",scope:this.config.scopes,code_challenge:o,code_challenge_method:"S256",tenant:this.config.tenant});e?.prompt&&a.set("prompt",e.prompt),e?.state&&a.set("state",e.state),window.location.href=`${s.authorization}?${a}`}async handleCallback(e){let n=new URL(e||window.location.href),o=n.searchParams.get("code"),s=n.searchParams.get("error");if(s)return{success:!1,error:n.searchParams.get("error_description")||s,code:s};if(!o)return{success:!1,error:"No authorization code in callback"};let a=sessionStorage.getItem("oluso_pkce_verifier");return sessionStorage.removeItem("oluso_pkce_verifier"),a?this.exchangeCodeForTokens(o,a,this.config.redirectUri||window.location.origin+"/callback"):{success:!1,error:"PKCE verifier not found"}}getUser(){return this.user}isAuthenticated(){return this.user!==null&&this.storage.getTokens()!==null}getAccessToken(){return this.storage.getTokens()?.accessToken??null}hasRole(e){return this.user?.roles.includes(e)??!1}hasAnyRole(...e){return e.some(n=>this.hasRole(n))}hasPermission(e){return this.user?.permissions.includes(e)??!1}async refreshToken(){let e=this.storage.getTokens();if(!e?.refreshToken)return!1;let n=await this.getEndpoints(),o=await fetch(n.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"refresh_token",client_id:this.config.clientId,refresh_token:e.refreshToken})});if(!o.ok)return this.logout(),!1;let s=await o.json();return this.processTokenResponse(s),!0}logout(e){let n=this.storage.getTokens();if(this.storage.clear(),this.user=null,this.config.onAuthStateChange?.(null),e?.redirect&&n?.idToken)if(this.resolvedEndpoints?.endSession||this.config.endpoints?.endSession){let o=new URLSearchParams({id_token_hint:n.idToken,post_logout_redirect_uri:e.postLogoutRedirectUri||window.location.origin});window.location.href=`${this.resolvedEndpoints?.endSession||this.config.endpoints?.endSession}?${o}`}else this.getEndpoints().then(o=>{let s=new URLSearchParams({id_token_hint:n.idToken,post_logout_redirect_uri:e.postLogoutRedirectUri||window.location.origin});window.location.href=`${o.endSession}?${s}`})}async fetchUserInfo(){let e=this.getAccessToken();if(!e)return null;let n=await this.getEndpoints(),o=await fetch(n.userinfo,{headers:{Authorization:`Bearer ${e}`}});if(!o.ok)return null;let s=await o.json();return this.user=this.claimsToUser(s),this.config.onAuthStateChange?.(this.user),this.user}async openAuthModal(e){let{verifier:n,challenge:o}=await this.generatePkce(),s=e==="signin"?this.config.signInJourney:this.config.signUpJourney,a=new URLSearchParams({journey:s,client_id:this.config.clientId,origin:window.location.origin,code_challenge:o,code_challenge_method:"S256",scope:this.config.scopes}),g=`${this.config.serverUrl}/embed/auth?${a}`;return new Promise(m=>{let f=document.createElement("div");f.style.cssText="position:fixed;inset:0;background:rgba(0,0,0,0.6);backdrop-filter:blur(4px);z-index:99999;display:flex;align-items:center;justify-content:center;padding:24px;";let x=document.createElement("div");x.style.cssText="background:#fff;border-radius:16px;width:100%;max-width:420px;max-height:90vh;overflow:hidden;box-shadow:0 25px 50px -12px rgba(0,0,0,0.25);";let L=document.createElement("div");L.style.cssText="display:flex;justify-content:flex-end;padding:12px 16px 0;";let C=document.createElement("button");C.innerHTML="×",C.style.cssText="background:none;border:none;cursor:pointer;color:#9ca3af;font-size:20px;padding:4px;border-radius:6px;",L.appendChild(C);let U=document.createElement("iframe");U.src=g,U.allow="camera; microphone",U.style.cssText="border:none;width:100%;min-height:300px;";let P=document.createElement("div");P.style.cssText="display:none;text-align:center;padding:10px 0;font-size:11px;color:#9ca3af;border-top:1px solid #e5e7eb;font-family:-apple-system,BlinkMacSystemFont,sans-serif;",P.innerHTML='Powered by <a href="https://oluso.io" target="_blank" rel="noopener" style="color:#9ca3af;text-decoration:none;">Oluso</a>',x.appendChild(L),x.appendChild(U),x.appendChild(P),f.appendChild(x),document.body.appendChild(f),document.body.style.overflow="hidden";let w=()=>{window.removeEventListener("message",$),document.removeEventListener("keydown",F),document.body.style.overflow="",f.remove()},I=()=>{w(),m({success:!1,error:"cancelled"})};C.addEventListener("click",I),f.addEventListener("click",T=>{T.target===f&&I()});let F=T=>{T.key==="Escape"&&I()};document.addEventListener("keydown",F);let $=async T=>{let H=new URL(this.config.serverUrl).origin;if(T.origin!==H)return;let A=T.data;if(!(!A||typeof A!="object"))if(A.type==="oluso:auth:code"){w();let Q=await this.exchangeCodeForTokens(A.code,n,"postmessage");m(Q)}else A.type==="oluso:auth:error"?(w(),m({success:!1,error:A.error})):A.type==="oluso:auth:ready"?P.style.display=A.hideBranding?"none":"block":A.type==="oluso:auth:resize"&&typeof A.height=="number"&&(U.style.height=`${A.height}px`)};window.addEventListener("message",$)})}async getEndpoints(){if(this.config.endpoints?.authorization&&this.config.endpoints?.token){let e=this.config.serverUrl;return{authorization:this.config.endpoints.authorization,token:this.config.endpoints.token,userinfo:this.config.endpoints.userinfo||`${e}/connect/userinfo`,endSession:this.config.endpoints.endSession||`${e}/connect/endsession`,jwks:this.config.endpoints.jwks||`${e}/.well-known/openid-configuration/jwks`}}return this.resolvedEndpoints?this.resolvedEndpoints:(this.discoveryPromise||(this.discoveryPromise=this.discoverEndpoints()),this.resolvedEndpoints=await this.discoveryPromise,this.resolvedEndpoints)}async discoverEndpoints(){let e=this.config.serverUrl,n=`${e}/.well-known/openid-configuration`;try{let o=await fetch(n);if(!o.ok)return this.defaultEndpoints();let s=await o.json();return{authorization:s.authorization_endpoint||`${e}/connect/authorize`,token:s.token_endpoint||`${e}/connect/token`,userinfo:s.userinfo_endpoint||`${e}/connect/userinfo`,endSession:s.end_session_endpoint||`${e}/connect/endsession`,jwks:s.jwks_uri||`${e}/.well-known/openid-configuration/jwks`}}catch{return this.defaultEndpoints()}}defaultEndpoints(){let e=this.config.serverUrl;return{authorization:`${e}/connect/authorize`,token:`${e}/connect/token`,userinfo:`${e}/connect/userinfo`,endSession:`${e}/connect/endsession`,jwks:`${e}/.well-known/openid-configuration/jwks`}}async executeJourney(e,n){let{verifier:o,challenge:s}=await this.generatePkce(),a=`${this.config.serverUrl}/api/public/journeys/${encodeURIComponent(e)}/start`,g=await fetch(a,{method:"POST",headers:this.buildHeaders(),body:JSON.stringify({data:n,clientId:this.config.clientId,codeChallenge:s,codeChallengeMethod:"S256",scope:this.config.scopes}),credentials:"include"});if(!g.ok){let m=await g.json().catch(()=>({message:"Auth failed"}));return{success:!1,error:m.error_description||m.message,code:m.error||m.code}}return this.handleJourneyResult(await g.json(),o)}async handleJourneyResult(e,n){if(e.completed&&e.code)return this.journeyVerifiers.delete(e.sessionId),this.exchangeCodeForTokens(e.code,n,"postmessage");if(e.status==="in_progress"){this.journeyVerifiers.set(e.sessionId,n);let o=e.step?.model?.errorMessage??e.step?.model?.formError;return{success:!1,requiresStep:e.step?.type??e.currentStep,sessionId:e.sessionId,step:e.step,redirectUrl:e.redirectUrl,error:typeof o=="string"?o:void 0}}return this.journeyVerifiers.delete(e.sessionId),{success:!1,error:e.errorDescription||e.error||"Authentication failed",code:e.error}}processTokenResponse(e){let n={accessToken:e.access_token,idToken:e.id_token,refreshToken:e.refresh_token,expiresAt:Math.floor(Date.now()/1e3)+(e.expires_in||3600),tokenType:e.token_type||"Bearer",scope:e.scope};return this.storage.setTokens(n),this.user=this.parseIdToken(n.idToken),this.config.onAuthStateChange?.(this.user),{success:!0,user:this.user,tokens:n}}parseIdToken(e){if(!e)return null;try{let n=e.split(".");if(n.length!==3)return null;let o=JSON.parse(atob(n[1].replace(/-/g,"+").replace(/_/g,"/")));return this.claimsToUser(o)}catch{return null}}claimsToUser(e){return{sub:e.sub,name:e.name||e.preferred_username,email:e.email,emailVerified:e.email_verified,roles:this.parseArrayClaim(e.role||e.roles),permissions:this.parseArrayClaim(e.permission||e.permissions),tenantId:e.tenant_id,claims:e}}parseArrayClaim(e){return e?Array.isArray(e)?e.map(String):typeof e=="string"?[e]:[]:[]}buildHeaders(){let e={"Content-Type":"application/json","X-Tenant-ID":this.config.tenant};return this.config.apiKey&&(e["X-API-Key"]=this.config.apiKey),e}async generatePkce(){let e=new Uint8Array(32);crypto.getRandomValues(e);let n=this.base64UrlEncode(e),o=new TextEncoder,s=await crypto.subtle.digest("SHA-256",o.encode(n)),a=this.base64UrlEncode(new Uint8Array(s));return{verifier:n,challenge:a}}base64UrlEncode(e){let n="";for(let o=0;o<e.length;o++)n+=String.fromCharCode(e[o]);return btoa(n).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}base64UrlDecode(e){let n=e.replace(/-/g,"+").replace(/_/g,"/"),o="=".repeat((4-n.length%4)%4),s=atob(n+o),a=new Uint8Array(s.length);for(let g=0;g<s.length;g++)a[g]=s.charCodeAt(g);return a.buffer}async exchangeCodeForTokens(e,n,o){let s=await this.getEndpoints(),a=await fetch(s.token,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:this.config.clientId,code:e,redirect_uri:o,code_verifier:n})});if(!a.ok){let m=await a.json().catch(()=>({error_description:"Token exchange failed"}));return{success:!1,error:m.error_description||m.error}}let g=await a.json();return this.processTokenResponse(g)}};var ze=`
|
|
101
|
+
.oluso-auth-overlay {
|
|
102
|
+
position: fixed;
|
|
103
|
+
inset: 0;
|
|
104
|
+
background: rgba(0, 0, 0, 0.6);
|
|
105
|
+
backdrop-filter: blur(4px);
|
|
106
|
+
-webkit-backdrop-filter: blur(4px);
|
|
107
|
+
z-index: 99999;
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: center;
|
|
111
|
+
padding: 24px;
|
|
112
|
+
opacity: 0;
|
|
113
|
+
visibility: hidden;
|
|
114
|
+
transition: opacity 0.25s ease, visibility 0.25s ease;
|
|
115
|
+
}
|
|
116
|
+
.oluso-auth-overlay.oluso-active {
|
|
117
|
+
opacity: 1;
|
|
118
|
+
visibility: visible;
|
|
119
|
+
}
|
|
120
|
+
.oluso-auth-modal {
|
|
121
|
+
background: #ffffff;
|
|
122
|
+
border-radius: 16px;
|
|
123
|
+
width: 100%;
|
|
124
|
+
max-width: 420px;
|
|
125
|
+
max-height: 90vh;
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
display: flex;
|
|
128
|
+
flex-direction: column;
|
|
129
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
130
|
+
transform: translateY(20px) scale(0.95);
|
|
131
|
+
transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
|
|
132
|
+
}
|
|
133
|
+
.oluso-active .oluso-auth-modal {
|
|
134
|
+
transform: translateY(0) scale(1);
|
|
135
|
+
}
|
|
136
|
+
.oluso-auth-header {
|
|
137
|
+
display: flex;
|
|
138
|
+
justify-content: flex-end;
|
|
139
|
+
padding: 12px 16px 0;
|
|
140
|
+
}
|
|
141
|
+
.oluso-auth-close {
|
|
142
|
+
background: none;
|
|
143
|
+
border: none;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
color: #9ca3af;
|
|
146
|
+
padding: 4px;
|
|
147
|
+
border-radius: 6px;
|
|
148
|
+
line-height: 1;
|
|
149
|
+
font-size: 20px;
|
|
150
|
+
transition: color 0.15s, background 0.15s;
|
|
151
|
+
}
|
|
152
|
+
.oluso-auth-close:hover {
|
|
153
|
+
color: #374151;
|
|
154
|
+
background: #f3f4f6;
|
|
155
|
+
}
|
|
156
|
+
.oluso-auth-iframe {
|
|
157
|
+
border: none;
|
|
158
|
+
width: 100%;
|
|
159
|
+
min-height: 300px;
|
|
160
|
+
transition: height 0.2s ease;
|
|
161
|
+
}
|
|
162
|
+
.oluso-auth-branding {
|
|
163
|
+
text-align: center;
|
|
164
|
+
padding: 10px 0;
|
|
165
|
+
font-size: 11px;
|
|
166
|
+
color: #9ca3af;
|
|
167
|
+
border-top: 1px solid #e5e7eb;
|
|
168
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
169
|
+
}
|
|
170
|
+
.oluso-auth-branding a {
|
|
171
|
+
color: #9ca3af;
|
|
172
|
+
text-decoration: none;
|
|
173
|
+
}
|
|
174
|
+
.oluso-auth-branding a:hover {
|
|
175
|
+
color: #6b7280;
|
|
176
|
+
}
|
|
177
|
+
@media (max-width: 480px) {
|
|
178
|
+
.oluso-auth-modal {
|
|
179
|
+
max-width: 100%;
|
|
180
|
+
max-height: 100vh;
|
|
181
|
+
height: 100%;
|
|
182
|
+
border-radius: 0;
|
|
183
|
+
}
|
|
184
|
+
.oluso-auth-overlay {
|
|
185
|
+
padding: 0;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
@media (prefers-color-scheme: dark) {
|
|
189
|
+
.oluso-auth-modal {
|
|
190
|
+
background: #1f2937;
|
|
191
|
+
}
|
|
192
|
+
.oluso-auth-close:hover {
|
|
193
|
+
color: #e5e7eb;
|
|
194
|
+
background: #374151;
|
|
195
|
+
}
|
|
196
|
+
.oluso-auth-branding {
|
|
197
|
+
border-top-color: #374151;
|
|
198
|
+
color: #6b7280;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
`,E=null,R=null,j=null,N=null,G=null,X=null,D=[],O=null,Y=null;function Ke(){N||(N=document.createElement("style"),N.id="oluso-auth-embed-styles",N.textContent=ze,document.head.appendChild(N))}function Be(){let i=new Uint8Array(32);crypto.getRandomValues(i);let e=me(i),n=new TextEncoder;return crypto.subtle.digest("SHA-256",n.encode(e)).then(o=>{let s=me(new Uint8Array(o));return{verifier:e,challenge:s}})}function me(i){let e="";for(let n=0;n<i.length;n++)e+=String.fromCharCode(i[n]);return btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}async function We(i){if(!E||!R||!Y)return{success:!1,error:"Not initialized"};let n=(await E.getEndpoints())?.token||`${R.serverUrl}/connect/token`,o=await fetch(n,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"authorization_code",client_id:R.clientId,code:i,redirect_uri:"postmessage",code_verifier:Y})});if(Y=null,!o.ok){let a=await o.json().catch(()=>({error_description:"Token exchange failed"}));return{success:!1,error:a.error_description||a.error}}let s=await o.json();return E.processTokenResponse(s)}function we(i){if(!R)return;let e=new URL(R.serverUrl).origin;if(i.origin!==e)return;let n=i.data;if(!(!n||typeof n!="object"))switch(n.type){case"oluso:auth:code":We(n.code).then(s=>{q(),s.success&&s.user&&D.forEach(a=>a(s.user)),O?.(s),O=null});break;case"oluso:auth:error":q();let o={success:!1,error:n.error};O?.(o),O=null;break;case"oluso:auth:ready":X&&(X.style.display=n.hideBranding?"none":"block");break;case"oluso:auth:resize":G&&typeof n.height=="number"&&(G.style.height=`${n.height}px`);break}}async function _e(i){if(!E||!R)return console.error("[OlusoAuth] Not initialized. Call OlusoAuth.init() first."),{success:!1,error:"Not initialized"};Ke();let{verifier:e,challenge:n}=await Be();Y=e;let o=i==="signin"?R.signInJourney||"signin":R.signUpJourney||"signup",s=new URLSearchParams({journey:o,client_id:R.clientId,origin:window.location.origin,code_challenge:n,code_challenge_method:"S256",scope:R.scopes||"openid profile email"}),a=`${R.serverUrl}/embed/auth?${s}`;j&&j.remove(),j=document.createElement("div"),j.className="oluso-auth-overlay",j.innerHTML=`
|
|
202
|
+
<div class="oluso-auth-modal">
|
|
203
|
+
<div class="oluso-auth-header">
|
|
204
|
+
<button class="oluso-auth-close" aria-label="Close">×</button>
|
|
205
|
+
</div>
|
|
206
|
+
<iframe class="oluso-auth-iframe" src="${a}" allow="camera; microphone"></iframe>
|
|
207
|
+
<div class="oluso-auth-branding" style="display:none">Powered by <a href="https://oluso.io" target="_blank" rel="noopener">Oluso</a></div>
|
|
208
|
+
</div>
|
|
209
|
+
`,document.body.appendChild(j),G=j.querySelector(".oluso-auth-iframe"),X=j.querySelector(".oluso-auth-branding"),j.querySelector(".oluso-auth-close")?.addEventListener("click",()=>{q(),O?.({success:!1,error:"cancelled"}),O=null}),j.addEventListener("click",f=>{f.target===j&&(q(),O?.({success:!1,error:"cancelled"}),O=null)});let m=f=>{f.key==="Escape"&&(q(),O?.({success:!1,error:"cancelled"}),O=null,document.removeEventListener("keydown",m))};return document.addEventListener("keydown",m),window.addEventListener("message",we),requestAnimationFrame(()=>{j.classList.add("oluso-active"),document.body.style.overflow="hidden"}),new Promise(f=>{O=f})}function q(){window.removeEventListener("message",we),j&&(j.classList.remove("oluso-active"),document.body.style.overflow="",setTimeout(()=>{j?.remove(),j=null,G=null,X=null},300))}function be(){document.addEventListener("click",i=>{let e=i.target.closest("[data-oluso-auth]");if(!e)return;i.preventDefault();let n=e.dataset.olusoAuth||"signin";n==="passkey"?ve():n==="fedcm"?ke():_e(n)})}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",be):be());function Ve(i){R=i,E=new V(i)}function Ye(i="signin"){return _e(i)}function Ge(i){D.push(i);let e=E?.getUser()??null;e&&i(e)}function Xe(){return E?.getUser()??null}function Qe(i){return E?.hasRole(i)??!1}function Ze(i){return E?.hasPermission(i)??!1}function et(i){E?.logout(i),D.forEach(e=>e(null))}async function ve(i){if(!E)return{success:!1,error:"Not initialized. Call OlusoAuth.init() first."};let e=await E.signInWithPasskey(i);return e.success&&e.user&&D.forEach(n=>n(e.user)),e}async function ke(i){if(!E)return{success:!1,error:"Not initialized. Call OlusoAuth.init() first."};let e=await E.signInWithFedCM(i);return e.success&&e.user&&D.forEach(n=>n(e.user)),e}return Oe(tt);})();
|
|
210
|
+
//# sourceMappingURL=embed.global.js.map
|