@tktchurch/auth 0.9.7 → 0.9.9

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/CHANGELOG.md CHANGED
@@ -2,6 +2,30 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.9.9] - 2026-07-18
6
+
7
+ ### Security
8
+
9
+ - Primary-email verification response bodies are now validated strictly;
10
+ malformed successful responses throw `AuthContractError`.
11
+ - Document that primary-email verification requires backend support for the
12
+ `identity:write` scope and recent, non-delegated authentication. Deploy and
13
+ validate that backend contract before releasing this SDK version.
14
+
15
+ ## [0.9.8] - 2026-07-18
16
+
17
+ ### Added
18
+
19
+ - `user.emailVerification.start({ email })` and
20
+ `user.emailVerification.verify({ code })` for the authenticated two-phase
21
+ primary-email verification flow.
22
+ - Typed email-verification request/response contracts in full and consumer
23
+ builds.
24
+
25
+ ### Fixed
26
+
27
+ - Map `email_verified` explicitly to `UserProfile.emailVerified`.
28
+
5
29
  ## [0.9.7] - 2026-07-18
6
30
 
7
31
  ### Changed
package/README.md CHANGED
@@ -34,6 +34,15 @@ const tokens = await auth.token.password({
34
34
  console.log(tokens.accessToken);
35
35
  ```
36
36
 
37
+ ## Primary email verification compatibility
38
+
39
+ SDK 0.9.9's `user.emailVerification.start()` / `verify()` contract requires a
40
+ backend exposing `POST /api/v1/users/me/email/verify` with the
41
+ `identity:write` scope and recent-authentication enforcement. Deploy and
42
+ validate that backend before releasing or adopting SDK 0.9.9. A successful
43
+ verification revokes the caller's existing sessions and tokens, so clients
44
+ must sign in again; the stable user identity remains the OIDC `sub`, not email.
45
+
37
46
  ## Authorization Code + PKCE (redirect flow)
38
47
 
39
48
  The recommended browser/SSR login flow. The SDK generates PKCE, `state`, and
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var Q=Object.defineProperty;var Le=Object.getOwnPropertyDescriptor;var Be=Object.getOwnPropertyNames;var Je=Object.prototype.hasOwnProperty;var He=(e,t)=>{for(var n in t)Q(e,n,{get:t[n],enumerable:!0})},Ve=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Be(t))!Je.call(e,r)&&r!==n&&Q(e,r,{get:()=>t[r],enumerable:!(o=Le(t,r))||o.enumerable});return e};var Qe=e=>Ve(Q({},"__esModule",{value:!0}),e);var Rt={};He(Rt,{AuthError:()=>i,DEFAULT_AUTHORIZE_SCOPE:()=>L,DEFAULT_TOKEN_STORAGE_KEY:()=>qe,MAX_STORED_TOKEN_BYTES:()=>H,MFARequiredAuthError:()=>S,PhoneOtpError:()=>k,assertValidAuthTokens:()=>O,createAuthClient:()=>$,createMemoryTokenStorage:()=>P,createPhoneOtpClient:()=>Ne,deriveCodeChallenge:()=>X,generateCodeVerifier:()=>Y,generateNonce:()=>j,generatePkce:()=>M,generateState:()=>D,isAuthError:()=>E,isUnrecoverableAuthError:()=>ue,parseStoredAuthTokens:()=>Ue,randomUrlSafeString:()=>x,safeParseStoredJson:()=>ze,sanitizePostAuthRedirect:()=>Fe,serializeAuthTokens:()=>De,timingSafeEqual:()=>N,validateStorageKey:()=>xe});module.exports=Qe(Rt);var i=class extends Error{code;status;details;constructor(t,n,o){super(n),this.name="AuthError",this.code=t,this.status=o?.status,this.details=o?.details}},S=class extends i{mfaMethods;constructor(t,n,o,r){super("mfa_required",t,{status:o,details:r}),this.name="MFARequiredAuthError",this.mfaMethods=n}};function We(e){switch(e){case"mfa_required":case"invalid_request":case"invalid_client":case"invalid_grant":case"unauthorized_client":case"unsupported_grant_type":case"invalid_scope":case"access_denied":case"unsupported_response_type":case"server_error":case"temporarily_unavailable":case"invalid_token":case"insufficient_scope":case"authentication_required":case"insufficient_user_authentication":return e;default:return"unknown_error"}}function Ge(e,t){if(!t)return new i("http_error",`Request failed with status ${e}`,{status:e});let n=We(t.error),o=t.error_description??t.reason??(t.error?`Auth error: ${t.error}`:`Request failed with status ${e}`);if(n==="mfa_required"){let r=Array.isArray(t.mfa_methods)?t.mfa_methods.filter(s=>typeof s=="string"):[];return new S(o,r,e,t)}return new i(n,o,{status:e,details:t})}async function ae(e){let t,n=await e.text();if(n)try{t=JSON.parse(n)}catch{t={reason:n}}return Ge(e.status,t)}function E(e){return e instanceof i}function ue(e){return E(e)?e.code==="invalid_client"||e.code==="invalid_grant"||e.code==="unauthorized_client"||e.code==="invalid_token":!1}function W(e){if(!Array.isArray(e))return;let t=e.filter(n=>typeof n=="object"&&n!==null&&typeof n.type=="string");return t.length>0?t:void 0}async function l(e){let t=await e.getTokens();if(!t?.accessToken)throw new i("invalid_token","No access token is available. Authenticate first.");return t.accessToken}function g(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>typeof t<"u"))}function b(e,t){let n=e.access_token,o=e.token_type,r=e.expires_in;if(typeof n!="string"||typeof o!="string"||typeof r!="number")throw new i("unknown_error","Unexpected token response payload.",{details:e});let s={accessToken:n,tokenType:o,expiresIn:r},a=typeof e.refresh_token=="string"?e.refresh_token:t;a&&(s.refreshToken=a),typeof e.scope=="string"&&(s.scope=e.scope),typeof e.id_token=="string"&&(s.idToken=e.id_token);let u=W(e.authorization_details);return u&&(s.authorizationDetails=u),s}function Ke(e){return{id:String(e.id??""),deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),browser:typeof e.browser=="string"?e.browser:void 0,os:typeof e.os=="string"?e.os:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0}}function G(e){return{id:String(e.id??""),deviceId:typeof e.device_id=="string"?e.device_id:void 0,deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),userAgent:typeof e.user_agent=="string"?e.user_agent:void 0,browser:typeof e.browser=="string"?e.browser:void 0,browserVersion:typeof e.browser_version=="string"?e.browser_version:void 0,os:typeof e.os=="string"?e.os:void 0,osVersion:typeof e.os_version=="string"?e.os_version:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isRevoked:!!e.is_revoked,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,requiresMfa:!!e.requires_mfa,accessTokenCount:typeof e.access_token_count=="number"?e.access_token_count:0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,expiresAt:typeof e.expires_at=="string"?e.expires_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0,revokedAt:typeof e.revoked_at=="string"?e.revoked_at:void 0,revocationReason:typeof e.revocation_reason=="string"?e.revocation_reason:void 0}}function K(e){return{success:!!e.success,sessionsRevoked:typeof e.sessions_revoked=="number"?e.sessions_revoked:0,tokensRevoked:typeof e.tokens_revoked=="number"?e.tokens_revoked:0}}function Ye(e){let t=Array.isArray(e.items)?e.items:[],o=e.metadata&&typeof e.metadata=="object"?e.metadata:{};return{items:t.filter(r=>typeof r=="object"&&r!==null).map(Ke),metadata:{page:typeof o.page=="number"?o.page:1,per:typeof o.per=="number"?o.per:t.length,total:typeof o.total=="number"?o.total:t.length}}}function de(e){return{async list(t){let n=await l(e),o=new URLSearchParams;typeof t?.page=="number"&&o.set("page",String(t.page)),typeof t?.perPage=="number"&&o.set("per_page",String(t.perPage)),t?.userId&&o.set("user_id",t.userId);let r=`/api/v1/sessions${o.size?`?${o.toString()}`:""}`,s=await e.http.request(r,{token:n});return Ye(s)},async current(){let t=await l(e),n=await e.http.request("/api/v1/sessions/current",{token:t});return G(n)},async get(t){let n=await l(e),o=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{token:n});return G(o)},async update(t,n){let o=await l(e),r=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"PATCH",token:o,body:g({device_name:n.deviceName,is_trusted:n.isTrusted})});return G(r)},async revoke(t,n){let o=await l(e),r=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"DELETE",token:o,body:g({reason:n?.reason})});return K(r)},async revokeAll(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all",{method:"POST",token:t});return K(n)},async revokeAllDevices(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all-devices",{method:"POST",token:t});return K(n)}}}function ce(){let e=globalThis.crypto;if(!e?.getRandomValues)throw new i("invalid_request","Web Crypto API is unavailable in this runtime. PKCE requires globalThis.crypto.");return e}function pe(e){let t="";for(let o of e)t+=String.fromCharCode(o);if(typeof btoa!="function")throw new i("server_error","base64UrlEncode requires globalThis.btoa (Web/Deno runtime).");return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function x(e=32){if(!Number.isInteger(e)||e<=0)throw new i("invalid_request","randomUrlSafeString length must be a positive integer.");let t=new Uint8Array(e);return ce().getRandomValues(t),pe(t)}function D(){return x(32)}function j(){return x(32)}function Y(){return x(32)}async function X(e){let t=ce();if(!t.subtle?.digest)throw new i("invalid_request","SubtleCrypto.digest is unavailable; cannot derive an S256 code challenge.");let n=new TextEncoder().encode(e),o=await t.subtle.digest("SHA-256",n);return pe(new Uint8Array(o))}async function M(e="S256"){let t=Y();if(e==="plain")return{codeVerifier:t,codeChallenge:t,codeChallengeMethod:"plain"};let n=await X(t);return{codeVerifier:t,codeChallenge:n,codeChallengeMethod:"S256"}}function N(e,t){let n=new TextEncoder().encode(e),o=new TextEncoder().encode(t),r=Math.max(n.length,o.length),s=n.length^o.length;for(let a=0;a<r;a+=1)s|=(n[a]??0)^(o[a]??0);return s===0}function Xe(e){return{active:!!e.active,scope:typeof e.scope=="string"?e.scope:void 0,clientId:typeof e.client_id=="string"?e.client_id:void 0,username:typeof e.username=="string"?e.username:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,exp:typeof e.exp=="number"?e.exp:void 0,iat:typeof e.iat=="number"?e.iat:void 0,sub:typeof e.sub=="string"?e.sub:void 0,authorizationDetails:W(e.authorization_details)}}function F(e){return{async password(t){let n=g({grant_type:"password",client_id:e.config.clientId,client_secret:e.config.clientSecret,username:t.username,email:t.email,password:t.password,scope:t.scope,mfa_code:t.mfaCode,mfa_backup_code:t.mfaBackupCode}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r},async refresh(t){let n=await e.getTokens(),o=t?.refreshToken??n?.refreshToken;if(!o)throw new i("invalid_request","No refresh token is available.");let r=g({grant_type:"refresh_token",client_id:e.config.clientId,client_secret:e.config.clientSecret,refresh_token:o,scope:t?.scope}),s=await e.http.request("/oauth/token",{method:"POST",body:r}),a=b(s,o);return await e.setTokens(a),a},async clientCredentials(t){let n=g({grant_type:"client_credentials",client_id:e.config.clientId,client_secret:e.config.clientSecret,scope:t?.scope}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r},async authorizationCode(t){let n=g({grant_type:"authorization_code",client_id:e.config.clientId,client_secret:e.config.clientSecret,code:t.code,redirect_uri:t.redirectUri,code_verifier:t.codeVerifier,scope:t.scope}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r},async revoke(t){let n=await e.getTokens(),o=t?.token??n?.accessToken;if(!o)throw new i("invalid_request","No token provided for revocation.");await e.http.request("/oauth/revoke",{method:"POST",body:g({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:o,token_type_hint:t?.tokenTypeHint})}),n&&(o===n.accessToken||o===n.refreshToken)&&await e.clearTokens()},async introspect(t){let n=await e.http.request("/oauth/introspect",{method:"POST",body:g({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:t.token})});return Xe(n)},async tokenExchange(t){let n=g({grant_type:"urn:ietf:params:oauth:grant-type:token-exchange",client_id:e.config.clientId,client_secret:e.config.clientSecret,subject_token:t.subjectToken,subject_token_type:t.subjectTokenType??"urn:ietf:params:oauth:token-type:access_token",requested_subject:t.requestedSubject,scope:t.scope,audience:t.audience}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r}}}function fe(e,t){let n=e.trim();if(!n)throw new i("invalid_request",`${t} is required.`);return n}async function _(e,t,n){let o=await l(e),r=n?.query,s=r&&Object.keys(r).length>0?`?${new URLSearchParams(Object.entries(r).filter(([,a])=>typeof a<"u").map(([a,u])=>[a,String(u)])).toString()}`:"";return e.http.request(`${t}${s}`,{method:n?.method,body:n?.body,token:o})}async function v(e,t,n){await _(e,t,n)}function A(e,t){return encodeURIComponent(fe(e,t))}function Ze(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(n=>typeof n=="string"):void 0;return{redirectUri:String(e.redirect_uri??""),code:typeof e.code=="string"?e.code:void 0,state:typeof e.state=="string"?e.state:void 0,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,mfaMethods:t,accessToken:typeof e.access_token=="string"?e.access_token:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,expiresIn:typeof e.expires_in=="number"?e.expires_in:void 0,scope:typeof e.scope=="string"?e.scope:void 0,idToken:typeof e.id_token=="string"?e.id_token:void 0}}function et(e){let t=Array.isArray(e.redirect_uris)?e.redirect_uris.filter(n=>typeof n=="string"&&n.length>0):[];return{clientId:String(e.client_id??""),name:String(e.name??""),description:typeof e.description=="string"?e.description:void 0,isFirstParty:!!e.is_first_party,redirectUris:t}}function tt(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(o=>typeof o=="string"):void 0,n=Array.isArray(e.uncovered_scopes)?e.uncovered_scopes.filter(o=>typeof o=="string"):void 0;return{consentSatisfied:!!e.consent_satisfied,requiresMfa:!!e.requires_mfa,mfaMethods:t,uncoveredScopes:n,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,code:typeof e.code=="string"?e.code:void 0,redirectUri:typeof e.redirect_uri=="string"?e.redirect_uri:void 0,state:typeof e.state=="string"?e.state:void 0}}function le(e){if(!e.password&&!e.accessToken)throw new i("invalid_request","Either password or accessToken is required for consent.")}function me(e,t){let n=new URL(e),o=new URL(t);if(n.origin!==o.origin||n.pathname!=="/oauth/authorize/consent")throw new i("invalid_request","callbackUrl must target /oauth/authorize/consent on the configured auth server.");return n}function he(e){async function t(o,r){le(r);let s=me(o,e.config.baseUrl),a={username:r.username,approved:r.approved??!0,requested_scopes:r.requestedScopes,mfa_code:r.mfaCode,mfa_backup_code:r.mfaBackupCode};r.password!==void 0&&(a.password=r.password);let u=await e.http.request(`${s.pathname}${s.search}`,{method:"POST",token:r.accessToken,body:a}),f=Ze(u);if(f.error==="mfa_required")throw new S(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}async function n(o,r){le(r);let s=me(o,e.config.baseUrl),a={username:r.username,requested_scopes:r.requestedScopes,mfa_code:r.mfaCode,mfa_backup_code:r.mfaBackupCode};r.password!==void 0&&(a.password=r.password);let u=await e.http.request(`${s.pathname}/evaluate${s.search}`,{method:"POST",token:r.accessToken,body:a}),f=tt(u);if(f.error==="mfa_required"||f.requiresMfa)throw new S(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}return{consent:t,evaluateConsent:n,consentWithCredentials(o){return t(o.callbackUrl,{username:o.username,password:o.password,accessToken:o.accessToken,approved:o.approved,requestedScopes:o.requestedScopes,mfaCode:o.mfaCode,mfaBackupCode:o.mfaBackupCode})},evaluateConsentWithCredentials(o){return n(o.callbackUrl,{username:o.username,password:o.password,accessToken:o.accessToken,requestedScopes:o.requestedScopes,mfaCode:o.mfaCode,mfaBackupCode:o.mfaBackupCode})}}}function ge(e){return{async publicClient(t){let n=await e.http.request(`/oauth/clients/${encodeURIComponent(t)}/public`);return et(n)},async discoverAuthorizationServer(){let t=await e.http.request("/.well-known/oauth-authorization-server");return{issuer:String(t.issuer??""),authorizationEndpoint:String(t.authorization_endpoint??""),tokenEndpoint:String(t.token_endpoint??""),jwksUri:typeof t.jwks_uri=="string"?t.jwks_uri:void 0,revocationEndpoint:typeof t.revocation_endpoint=="string"?t.revocation_endpoint:void 0,introspectionEndpoint:typeof t.introspection_endpoint=="string"?t.introspection_endpoint:void 0,registrationEndpoint:typeof t.registration_endpoint=="string"?t.registration_endpoint:void 0,scopesSupported:Array.isArray(t.scopes_supported)?t.scopes_supported.filter(n=>typeof n=="string"):void 0,responseTypesSupported:Array.isArray(t.response_types_supported)?t.response_types_supported.filter(n=>typeof n=="string"):[],grantTypesSupported:Array.isArray(t.grant_types_supported)?t.grant_types_supported.filter(n=>typeof n=="string"):void 0,codeChallengeMethodsSupported:Array.isArray(t.code_challenge_methods_supported)?t.code_challenge_methods_supported.filter(n=>typeof n=="string"):void 0,pushedAuthorizationRequestEndpoint:typeof t.pushed_authorization_request_endpoint=="string"?t.pushed_authorization_request_endpoint:void 0,requirePushedAuthorizationRequests:typeof t.require_pushed_authorization_requests=="boolean"?t.require_pushed_authorization_requests:void 0,authorizationDetailsTypesSupported:Array.isArray(t.authorization_details_types_supported)?t.authorization_details_types_supported.filter(n=>typeof n=="string"):void 0,raw:t}}}}var L="openid profile email offline_access",ye=new Set(["response_type","client_id","redirect_uri","scope","state","nonce","code_challenge","code_challenge_method","prompt","login_hint","authorization_details","request_uri"]);function nt(e){if(typeof e=="string"){let t=e.indexOf("?"),n=t>=0?e.slice(t+1):e;return new URLSearchParams(n)}return e instanceof URLSearchParams?e:"raw"in e&&typeof e.raw=="object"?new URLSearchParams(e.raw):new URLSearchParams(e)}function _e(e){let t=nt(e),n={};return t.forEach((o,r)=>{n[r]=o}),{code:t.get("code")??void 0,state:t.get("state")??void 0,error:t.get("error")??void 0,errorDescription:t.get("error_description")??void 0,errorUri:t.get("error_uri")??void 0,raw:n}}function ke(e){let t=F(e);return{...he(e),async createRequest(o){if(!o.redirectUri?.trim())throw new i("invalid_request","redirectUri is required to build an authorization request.");let r=o.scope??L,s=o.state??D(),a=o.nonce??j(),u=await M(o.codeChallengeMethod??"S256"),f=o.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,R=new URL(f),m=R.searchParams;m.set("response_type",o.responseType??"code"),m.set("client_id",e.config.clientId),m.set("redirect_uri",o.redirectUri),m.set("scope",r),m.set("state",s),m.set("nonce",a),m.set("code_challenge",u.codeChallenge),m.set("code_challenge_method",u.codeChallengeMethod),o.authorizationDetails&&o.authorizationDetails.length>0&&m.set("authorization_details",JSON.stringify(o.authorizationDetails)),o.prompt&&m.set("prompt",o.prompt),o.loginHint&&m.set("login_hint",o.loginHint);for(let[w,U]of Object.entries(o.extraParams??{})){if(ye.has(w))throw new i("invalid_request",`extraParams may not override the reserved authorization parameter "${w}".`);m.set(w,U)}return{url:R.toString(),state:s,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:o.redirectUri,scope:r}},async pushAuthorizationRequest(o){if(!o.redirectUri?.trim())throw new i("invalid_request","redirectUri is required to push an authorization request.");let r=o.scope??L,s=o.state??D(),a=o.nonce??j(),u=await M(o.codeChallengeMethod??"S256"),f={response_type:o.responseType??"code",client_id:e.config.clientId,redirect_uri:o.redirectUri,scope:r,state:s,nonce:a,code_challenge:u.codeChallenge,code_challenge_method:u.codeChallengeMethod};e.config.clientSecret&&(f.client_secret=e.config.clientSecret),o.authorizationDetails&&o.authorizationDetails.length>0&&(f.authorization_details=JSON.stringify(o.authorizationDetails));for(let[h,c]of Object.entries(o.extraParams??{})){if(ye.has(h))throw new i("invalid_request",`extraParams may not override the reserved authorization parameter "${h}".`);f[h]=c}let R=await e.http.request("/oauth/par",{method:"POST",body:f}),m=R.request_uri,w=R.expires_in;if(typeof m!="string"||typeof w!="number")throw new i("unknown_error","Unexpected pushed authorization response payload.",{details:R});let U=o.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,p=new URL(U);return p.searchParams.set("client_id",e.config.clientId),p.searchParams.set("request_uri",m),{requestUri:m,expiresIn:w,request:{url:p.toString(),state:s,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:o.redirectUri,scope:r,requestUri:m}}},parseCallback:_e,async probeAuthorize(o){let r=await e.http.requestRaw(o,{headers:{Accept:"application/json"},redirect:"manual"}),s=r.headers.get("location");if(s&&r.status>=300&&r.status<400)return{kind:"redirect",location:s,status:r.status};let a=await r.text(),u=a?JSON.parse(a):{};if(!r.ok)throw new i("server_error",typeof u.error_description=="string"?u.error_description:"Authorization probe failed",{status:r.status,details:u});let f=typeof u.authorization_url=="string"?u.authorization_url:void 0;return{kind:"json",status:r.status,authorizationUrl:f,payload:u}},async handleCallback(o){let s=typeof o.callback=="object"&&!(o.callback instanceof URLSearchParams)&&"raw"in o.callback?o.callback:_e(o.callback);if(s.error)throw new i("access_denied",s.errorDescription??`Authorization failed: ${s.error}`,{details:s.raw});if(!s.state||!N(s.state,o.expectedState))throw new i("invalid_request","State mismatch on authorization callback (possible CSRF).");if(!s.code)throw new i("invalid_request","Authorization callback is missing the `code` parameter.");return t.authorizationCode({code:s.code,redirectUri:o.redirectUri,codeVerifier:o.codeVerifier,scope:o.scope})}}}function q(e){let t=e.step_id,n=e.step_type,o=e.name,r=e.order,s=e.is_required,a=e.timeout;if(typeof t!="string"||typeof n!="string"||typeof o!="string"||typeof r!="number"||typeof s!="boolean"||typeof a!="number")throw new i("unknown_error","Unexpected flow step payload.",{details:e});return{stepId:t,stepType:n,name:o,description:typeof e.description=="string"?e.description:void 0,order:r,isRequired:s,timeout:a,inputSchema:e.input_schema&&typeof e.input_schema=="object"?e.input_schema:void 0}}function Z(e){let t=e.current_step,n=e.remaining_steps;if(!t||typeof t!="object")throw new i("unknown_error","Missing current_step in flow response.",{details:e});let o=e.continuation_token;if(typeof o!="string"||!o)throw new i("unknown_error","Missing continuation_token in flow response.",{details:e});return{sessionId:String(e.session_id??""),flowId:String(e.flow_id??""),flowName:String(e.flow_name??""),currentStep:q(t),remainingSteps:Array.isArray(n)?n.filter(r=>typeof r=="object"&&r!==null).map(q):[],expiresAt:String(e.expires_at??""),continuationToken:o}}function ot(e){return{sessionId:String(e.session_id??""),status:String(e.status??""),purpose:String(e.purpose??""),currentStep:e.current_step&&typeof e.current_step=="object"?q(e.current_step):void 0,completedSteps:Array.isArray(e.completed_steps)?e.completed_steps.filter(t=>typeof t=="string"):[],remainingSteps:Array.isArray(e.remaining_steps)?e.remaining_steps.filter(t=>typeof t=="object"&&t!==null).map(q):[],failedAttempts:typeof e.failed_attempts=="number"?e.failed_attempts:0,expiresAt:String(e.expires_at??""),lastActivityAt:String(e.last_activity_at??"")}}async function ee(e,t){let n=t.status;if(n==="error"||typeof t.error=="string"&&n!=="in_progress"&&n!=="complete")throw new i("invalid_request",typeof t.error=="string"?t.error:"Flow step failed.",{details:t});if(n==="in_progress"){let o=t.next_step,r=t.remaining_steps;if(!o||typeof o!="object")throw new i("unknown_error","Missing next_step in flow step response.",{details:t});let s=t.debug&&typeof t.debug=="object"&&!Array.isArray(t.debug)?t.debug:void 0;return{status:"in_progress",sessionId:String(t.session_id??""),nextStep:q(o),completedSteps:Array.isArray(t.completed_steps)?t.completed_steps.filter(u=>typeof u=="string"):[],remainingSteps:Array.isArray(r)?r.filter(u=>typeof u=="object"&&u!==null).map(q):[],debug:s}}if(n==="complete"){let o=b(t);return await e.setTokens(o),{status:"complete",accessToken:o.accessToken,refreshToken:o.refreshToken,tokenType:o.tokenType,expiresIn:o.expiresIn,scope:o.scope,amr:Array.isArray(t.amr)?t.amr.filter(s=>typeof s=="string"):[],acr:typeof t.acr=="string"?t.acr:""}}throw new i("unknown_error","Unknown flow step status.",{details:t})}function be(e){return{async initAuthentication(t){let n=await e.http.request("/oauth/authenticate/init",{method:"POST",body:g({client_id:t?.clientId??e.config.clientId,username:t?.username,flow_type:t?.flowType})});return Z(n)},async executeStep(t){let n=await e.http.request("/oauth/authenticate/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return ee(e,n)},async initRegistration(t){let n=await e.http.request("/oauth/register/init",{method:"POST",body:g({client_id:t?.clientId??e.config.clientId,invite_code:t?.inviteCode,flow_type:t?.flowType})});return Z(n)},async executeRegistrationStep(t){let n=await e.http.request("/oauth/register/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return ee(e,n)},async getStatus(t,n){let o=new URLSearchParams({continuation_token:n}),r=await e.http.request(`/oauth/flow/status/${encodeURIComponent(t)}?${o}`);return ot(r)},async initRecovery(t){let n=await e.http.request("/oauth/recovery/init",{method:"POST",body:g({client_id:t?.clientId??e.config.clientId,recovery_type:t?.recoveryType,redirect_uri:t?.redirectUri})});return Z(n)},async executeRecoveryStep(t){let n=await e.http.request("/oauth/recovery/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return ee(e,n)}}}function B(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function rt(e){return{issuer:String(e.issuer??""),authorizationEndpoint:String(e.authorization_endpoint??""),tokenEndpoint:String(e.token_endpoint??""),userinfoEndpoint:typeof e.userinfo_endpoint=="string"?e.userinfo_endpoint:void 0,jwksUri:String(e.jwks_uri??""),revocationEndpoint:typeof e.revocation_endpoint=="string"?e.revocation_endpoint:void 0,introspectionEndpoint:typeof e.introspection_endpoint=="string"?e.introspection_endpoint:void 0,responseTypesSupported:B(e.response_types_supported),grantTypesSupported:B(e.grant_types_supported),scopesSupported:B(e.scopes_supported),codeChallengeMethodsSupported:B(e.code_challenge_methods_supported),raw:e}}function st(e){return{sub:String(e.sub??""),name:typeof e.name=="string"?e.name:void 0,givenName:typeof e.given_name=="string"?e.given_name:void 0,familyName:typeof e.family_name=="string"?e.family_name:void 0,middleName:typeof e.middle_name=="string"?e.middle_name:void 0,nickname:typeof e.nickname=="string"?e.nickname:void 0,preferredUsername:typeof e.preferred_username=="string"?e.preferred_username:void 0,profile:typeof e.profile=="string"?e.profile:void 0,picture:typeof e.picture=="string"?e.picture:void 0,website:typeof e.website=="string"?e.website:void 0,gender:typeof e.gender=="string"?e.gender:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0,zoneinfo:typeof e.zoneinfo=="string"?e.zoneinfo:void 0,locale:typeof e.locale=="string"?e.locale:void 0,updatedAt:typeof e.updated_at=="number"?e.updated_at:void 0,email:typeof e.email=="string"?e.email:void 0,emailVerified:typeof e.email_verified=="boolean"?e.email_verified:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,phoneNumberVerified:typeof e.phone_number_verified=="boolean"?e.phone_number_verified:void 0}}function Re(e){return{async userInfo(){let t=await l(e),n=await e.http.request("/oauth/userinfo",{token:t});return st(n)},async discover(){let t=await e.http.request("/.well-known/openid-configuration");return rt(t)},async jwks(){let t=await e.http.request("/oauth/jwks");return{keys:Array.isArray(t.keys)?t.keys.filter(o=>typeof o=="object"&&o!==null):[]}}}}function J(e){return{...e,id:typeof e.id=="string"?e.id:"",organizationId:typeof e.organization_id=="string"?e.organization_id:void 0,email:typeof e.email=="string"?e.email:void 0,username:typeof e.username=="string"?e.username:void 0,firstName:typeof e.first_name=="string"?e.first_name:void 0,lastName:typeof e.last_name=="string"?e.last_name:void 0,isActive:typeof e.is_active=="boolean"?e.is_active:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0,mfaEnabled:typeof e.mfa_enabled=="boolean"?e.mfa_enabled:void 0}}function te(e){return{id:String(e.id??""),name:typeof e.name=="string"?e.name:void 0,email:typeof e.email=="string"?e.email:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,relationship:typeof e.relationship=="string"?e.relationship:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0}}function it(e){return{id:String(e.id??""),provider:String(e.provider??""),providerUserId:typeof e.provider_user_id=="string"?e.provider_user_id:void 0,email:typeof e.email=="string"?e.email:void 0,isPrimary:typeof e.is_primary=="boolean"?e.is_primary:void 0}}function we(e){return at(e)}function at(e){return{async me(){let t=await l(e),n=await e.http.request("/api/v1/users/me",{token:t});return J(n)},async updateMe(t){let n=await _(e,"/api/v1/users/me",{method:"PATCH",body:t});return J(n)},async changePassword(t){await v(e,"/api/v1/users/me/password",{method:"POST",body:{current_password:t.currentPassword,new_password:t.newPassword}})},async deleteAvatar(){let t=await _(e,"/api/v1/users/me/avatar",{method:"DELETE"});return J(t)},async uploadAvatar(t,n="avatar.jpg"){let o=await l(e),r=new FormData,s=t instanceof Blob?t:new Blob([new Uint8Array(t)]);r.append("avatar",s,n);let a=await e.http.request("/api/v1/users/me/avatar",{method:"POST",token:o,body:r});return J(a)},async verifyPhone(t){return _(e,"/api/v1/users/me/phone/verify",{method:"POST",body:t})},async verifyRecoveryEmail(t){return _(e,"/api/v1/users/me/recovery-email/verify",{method:"POST",body:t})},async securityOverview(){return _(e,"/api/v1/users/me/security-overview")},recoveryContacts:{async list(){let t=await _(e,"/api/v1/users/me/recovery-contacts");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(te):[]},async create(t){let n=await _(e,"/api/v1/users/me/recovery-contacts",{method:"POST",body:t});return te(n)},async update(t,n){let o=await _(e,`/api/v1/users/me/recovery-contacts/${A(t,"contactId")}`,{method:"PATCH",body:n});return te(o)},async delete(t){await v(e,`/api/v1/users/me/recovery-contacts/${A(t,"contactId")}`,{method:"DELETE"})}},identities:{async list(){let t=await _(e,"/api/v1/users/me/identities");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(it):[]},async unlink(t){await v(e,`/api/v1/users/me/identities/${A(t,"identityId")}`,{method:"DELETE"})},async setPrimary(t){return _(e,`/api/v1/users/me/identities/${A(t,"identityId")}/primary`,{method:"PATCH"})}},async deleteMe(t){await v(e,"/api/v1/users/me",{method:"DELETE",body:{password:t.password}})}}}function C(e){return e&&typeof e=="object"?e:{}}function Se(e){return{async registerBegin(t){let n=await l(e),o=await e.http.request("/api/v1/users/me/webauthn/register/begin",{method:"POST",token:n,body:t});return C(o)},async registerFinish(t){let n=await l(e),o=await e.http.request("/api/v1/users/me/webauthn/register/finish",{method:"POST",token:n,body:t});return C(o)},async authenticateBegin(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/begin",{method:"POST",body:t});return C(n)},async authenticateFinish(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/finish",{method:"POST",body:t}),o=C(n);if(typeof o.access_token=="string"){let r=b(o);await e.setTokens(r)}return o},async credentials(){let t=await l(e),n=await e.http.request("/api/v1/users/me/webauthn/credentials",{token:t});return C(n)},async removeCredential(t,n){let o=await l(e);await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}`,{method:"DELETE",token:o,body:n?.password?{password:n.password}:void 0})},async renameCredential(t,n){let o=await l(e),r=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/rename`,{method:"PATCH",token:o,body:n});return C(r)},async setPrimaryCredential(t){let n=await l(e),o=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/primary`,{method:"POST",token:n});return C(o)}}}function ut(e){return{isActive:!!(e.is_active??e.isActive),message:typeof e.message=="string"?e.message:void 0,scheduledStart:typeof e.scheduled_start=="string"?e.scheduled_start:void 0,scheduledEnd:typeof e.scheduled_end=="string"?e.scheduled_end:void 0,...e}}function ve(e){return{async status(){let t=await e.http.request("/api/v1/maintenance/status");return ut(t)}}}var dt=128,ne=254;function T(e,t){if(typeof e!="string")return;let n=e.trim();if(!(!n||n.length>t))return n}function Te(e){return{async request(t){let n=g({email:T(t.email,ne),identifier:T(t.identifier,ne),recovery_email:T(t.recoveryEmail,ne),phone_number:T(t.phoneNumber,32),member_id:T(t.memberId,64),security_question:T(t.securityQuestion,256),security_answer:T(t.securityAnswer,256),redirect_uri:T(t.redirectUri,2048)}),o=await e.http.request("/oauth/password/reset/request",{method:"POST",body:n});return{ok:!!o.ok,message:String(o.message??"")}},async validate(t){let n=t.trim();if(!n)throw new i("invalid_request","token is required.");let o=await e.http.request(`/oauth/password/reset/validate?token=${encodeURIComponent(n)}`);return{ok:!!o.ok,valid:!!o.valid,expiresAt:typeof o.expires_at=="string"?o.expires_at:void 0}},async complete(t){if(!t.token.trim())throw new i("invalid_request","token is required.");if(!t.password||t.password.length>dt)throw new i("invalid_request","password is required and must be <= 128 characters.");let n=await e.http.request("/oauth/password/reset/complete",{method:"POST",body:{token:t.token.trim(),password:t.password,password_confirm:t.passwordConfirm}});return{ok:!!n.ok,message:String(n.message??"")}}}}function ct(e){return{id:String(e.id??""),deviceName:String(e.device_name??""),isVerified:!!e.is_verified,isPrimary:!!e.is_primary,createdAt:typeof e.created_at=="string"?e.created_at:void 0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0}}function Ae(e){return{async setup(t){let n=t.deviceName?.trim();if(!n||n.length>128)throw new i("invalid_request","deviceName is required.");let o=await _(e,"/api/v1/users/me/mfa/setup",{method:"POST",body:{device_name:n}});return{deviceId:String(o.device_id??""),secret:String(o.secret??""),qrCodeUri:String(o.qr_code_uri??""),backupCodes:Array.isArray(o.backup_codes)?o.backup_codes.filter(r=>typeof r=="string"):[],algorithm:String(o.algorithm??""),digits:typeof o.digits=="number"?o.digits:6,period:typeof o.period=="number"?o.period:30}},async verify(t){return _(e,"/api/v1/users/me/mfa/verify",{method:"POST",body:{device_id:t.deviceId,totp_code:t.totpCode}})},async devices(){let t=await _(e,"/api/v1/users/me/mfa/devices");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(ct):[]},async removeDevice(t){await v(e,`/api/v1/users/me/mfa/devices/${A(t,"deviceId")}`,{method:"DELETE"})},async regenerateBackupCodes(){let t=await _(e,"/api/v1/users/me/mfa/backup-codes/regenerate",{method:"POST"});return{backupCodes:Array.isArray(t.backup_codes)?t.backup_codes.filter(n=>typeof n=="string"):[]}},async disable(t){await v(e,"/api/v1/users/me/mfa/disable",{method:"POST",body:g({password:t?.password})})}}}var Ce="https://prod-auth.tktchurch.com",pt=new Set(["localhost","127.0.0.1","[::1]"]);function ft(e){return pt.has(e.toLowerCase())}function oe(e,t={}){let n=(e??Ce).trim();if(!n)return oe(Ce,t);let r=(/^https?:\/\//i.test(n)?n:`https://${n}`).replace(/\/+$/,""),s;try{s=new URL(r)}catch{throw new i("invalid_request","baseUrl must be a valid absolute URL.")}if(s.protocol==="http:"&&!t.allowInsecureTransport&&!ft(s.hostname))throw new i("invalid_request","baseUrl must use HTTPS. Set allowInsecureTransport=true only for trusted local development.");return r}function lt(e,t){if(!e&&t<=0)return{cleanup:()=>{}};let n=new AbortController,o,r=()=>{n.abort(e?.reason)};return e&&(e.aborted?n.abort(e.reason):e.addEventListener("abort",r,{once:!0})),t>0&&(o=setTimeout(()=>{n.abort(new Error(`Request timed out after ${t}ms`))},t)),{signal:n.signal,cleanup:()=>{o&&clearTimeout(o),e&&e.removeEventListener("abort",r)}}}function mt(e,t){return/^https?:\/\//i.test(t)?t:`${e}${t.startsWith("/")?t:`/${t}`}`}function ht(e,t,n){let o=new Headers(e);return t&&new Headers(t).forEach((s,a)=>{o.set(a,s)}),n&&!o.has("Authorization")&&o.set("Authorization",`Bearer ${n}`),o}function Pe(e){return{async request(t,n){let o=await this.requestRaw(t,n);if(!o.ok)throw await ae(o);if(o.status===204)return;let r=await o.text();if(r)return JSON.parse(r)},async requestRaw(t,n){let o=mt(e.baseUrl,t),r=ht(e.defaultHeaders,n?.headers,n?.token),{signal:s,cleanup:a}=lt(n?.signal,e.timeoutMs),u={method:n?.method??"GET",headers:r,signal:s,redirect:n?.redirect};typeof n?.body<"u"&&(n.body instanceof FormData?u.body=n.body:(r.has("Content-Type")||r.set("Content-Type","application/json"),u.body=JSON.stringify(n.body)));try{return await e.fetch(o,u)}catch(f){throw s?.aborted??!1?new i("timeout",`Request timed out: ${o}`,{details:f}):new i("network_error",`Network request failed: ${o}`,{details:f})}finally{a()}}}}var qe="@tktchurch/auth/tokens",H=32768,Oe=new Set(["accessToken","tokenType","expiresIn","refreshToken","scope","idToken","authorizationDetails"]),Ie=new Set(["__proto__","constructor","prototype"]),gt=/^[\w@./:-]{1,128}$/;function se(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Ee(e){return typeof e=="string"&&e.length>0}function re(e){return typeof e=="string"&&e.length>0?e:void 0}function O(e){if(!se(e))throw new i("invalid_request","Token storage rejected a non-object token payload.");for(let s of Object.keys(e))if(!Oe.has(s))throw new i("invalid_request",`Token storage rejected unknown field "${s}".`);if(!Ee(e.accessToken))throw new i("invalid_request","Token storage requires a non-empty accessToken.");if(!Ee(e.tokenType))throw new i("invalid_request","Token storage requires a non-empty tokenType.");if(typeof e.expiresIn!="number"||!Number.isFinite(e.expiresIn)||e.expiresIn<0)throw new i("invalid_request","Token storage requires a non-negative numeric expiresIn.");let t={accessToken:e.accessToken,tokenType:e.tokenType,expiresIn:e.expiresIn},n=re(e.refreshToken);n&&(t.refreshToken=n);let o=re(e.scope);o&&(t.scope=o);let r=re(e.idToken);if(r&&(t.idToken=r),typeof e.authorizationDetails<"u"){if(!Array.isArray(e.authorizationDetails)||!e.authorizationDetails.every(s=>se(s)&&typeof s.type=="string"))throw new i("invalid_request","Token storage rejected malformed authorizationDetails.");t.authorizationDetails=e.authorizationDetails}return t}function Ue(e){if(!se(e))return null;for(let t of Object.keys(e))if(Ie.has(t)||!Oe.has(t))return null;try{return O(e)}catch{return null}}function ze(e){return JSON.parse(e,(t,n)=>{if(Ie.has(t))throw new SyntaxError("Forbidden JSON key in stored token payload.");return n})}function xe(e){let t=e.trim();if(!t)throw new i("invalid_request","Token storage key must be a non-empty string.");if(!gt.test(t))throw new i("invalid_request","Token storage key contains unsupported characters or exceeds 128 characters.");return t}function De(e){let t=O(e),n=JSON.stringify(t);if(n.length>H)throw new i("invalid_request",`Serialized token payload exceeds ${H} bytes.`);return n}var ie=class{state=null;get(){return this.state}set(t){if(!t){this.clear();return}this.state=O(t)}clear(){this.state=null}};function P(){return new ie}function yt(){return typeof window<"u"&&typeof window.document<"u"}function _t(e){if(e)return e;if(typeof globalThis.fetch=="function")return globalThis.fetch.bind(globalThis);throw new i("invalid_request","No fetch implementation available. Provide config.fetch.")}function je(e){if(!e.clientId?.trim())throw new i("invalid_request","clientId is required.");if(yt()&&e.clientSecret&&!e.allowClientSecretInBrowser)throw new i("invalid_request","clientSecret in browser runtime is blocked by default. Set allowClientSecretInBrowser=true to override.");return{clientId:e.clientId,clientSecret:e.clientSecret,baseUrl:oe(e.baseUrl,{allowInsecureTransport:e.allowInsecureTransport??!1}),fetch:_t(e.fetch),storage:e.storage??P(),timeoutMs:e.timeoutMs??15e3,defaultHeaders:e.defaultHeaders??{},autoRefresh:e.autoRefresh??!0,allowClientSecretInBrowser:e.allowClientSecretInBrowser??!1,allowInsecureTransport:e.allowInsecureTransport??!1}}function $(e){let t=je(e),n=Pe({baseUrl:t.baseUrl,fetch:t.fetch,timeoutMs:t.timeoutMs,defaultHeaders:t.defaultHeaders}),o=async()=>await t.storage.get(),r=async u=>{await t.storage.set(u)},s=async()=>{await t.storage.clear()},a={config:t,http:n,getTokens:o,setTokens:r,clearTokens:s};return{token:F(a),flow:be(a),oidc:Re(a),authorize:ke(a),user:we(a),sessions:de(a),webauthn:Se(a),passwordReset:Te(a),mfa:Ae(a),maintenance:ve(a),oauth:ge(a),tokens:{get:o,set:r,clear:s}}}var k=class extends Error{name="PhoneOtpError"};function I(e,t){return e instanceof k?e:E(e)?new k(e.message||t):e instanceof Error&&e.message?new k(e.message):new k(t)}function Me(e){if(!E(e)||typeof e.status!="number")return!1;let t=e.status;return t>=400&&t<500&&t!==429}function $e(e){if(e.status!=="in_progress"||!e.debug)return;let t=e.debug.verification_code;return typeof t=="string"?t:void 0}function kt(e){return{...e,id:typeof e.id=="string"?e.id:"",first_name:typeof e.first_name=="string"?e.first_name:typeof e.firstName=="string"?e.firstName:void 0,last_name:typeof e.last_name=="string"?e.last_name:typeof e.lastName=="string"?e.lastName:void 0,email:typeof e.email=="string"?e.email:void 0,phone_number:typeof e.phone_number=="string"?e.phone_number:typeof e.phoneNumber=="string"?e.phoneNumber:void 0,phone_country_code:typeof e.phone_country_code=="string"?e.phone_country_code:typeof e.phoneCountryCode=="string"?e.phoneCountryCode:void 0,phone_verified:typeof e.phone_verified=="boolean"?e.phone_verified:typeof e.phoneVerified=="boolean"?e.phoneVerified:void 0,profile_picture_url:typeof e.profile_picture_url=="string"?e.profile_picture_url:typeof e.profilePictureUrl=="string"?e.profilePictureUrl:void 0,picture:typeof e.picture=="string"?e.picture:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0}}function Ne(e){let t=e.auth,n=e.guestProfile??{firstName:"Guest",lastName:"User"},o=n.emailDomain??"registrations.tktchurch.local",r=n.emailLocalPrefix??"reg";function s(){return t||$({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:P(),autoRefresh:!1})}async function a(p,h){let c=s(),d=await c.flow.initAuthentication({flowType:"phone_only",username:h}),y=await c.flow.executeStep({sessionId:d.sessionId,stepId:d.currentStep.stepId,continuationToken:d.continuationToken,credential:p});if(y.status!=="in_progress")throw new k("Unexpected sign-in response.");return{oauthSessionId:d.sessionId,verifyStepId:y.nextStep.stepId,mode:"authentication",continuationToken:d.continuationToken,debugCode:$e(y)}}async function u(p){let h=s(),c=await h.flow.initRegistration({flowType:"phone_registration"}),d=await h.flow.executeRegistrationStep({sessionId:c.sessionId,stepId:c.currentStep.stepId,continuationToken:c.continuationToken,credential:p});if(d.status!=="in_progress")throw new k("Unexpected verification response.");return{oauthSessionId:c.sessionId,verifyStepId:d.nextStep.stepId,mode:"registration",continuationToken:c.continuationToken,debugCode:$e(d)}}async function f(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await u(d)}catch(y){if(!Me(y))throw I(y,"Could not send the code. Please try again.");try{return await a(d,c)}catch{throw I(y,"Could not send the code. Please try again.")}}}async function R(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await a(d,c)}catch(y){if(!Me(y))throw I(y,"Could not start sign-in.");try{return await u(d)}catch{throw I(y,"Could not start sign-in.")}}}async function m(p,h,c,d,y,z){return h==="registration"?await p.flow.executeRegistrationStep({sessionId:c,stepId:d,continuationToken:y,credential:z}):await p.flow.executeStep({sessionId:c,stepId:d,continuationToken:y,credential:z})}async function w(p,h){let c=s();try{let d=await m(c,p.mode,p.oauthSessionId,p.verifyStepId,p.continuationToken,{code:h}),y=0;for(;d.status==="in_progress"&&y<6;){y++;let z=d.nextStep.stepType,V={};z==="profile_info"?V={first_name:n.firstName,last_name:n.lastName,email:`${r}+${p.oauthSessionId.slice(0,8).toLowerCase()}@${o}`}:z==="terms_acceptance"&&(V={accepted:"true"}),d=await m(c,p.mode,p.oauthSessionId,d.nextStep.stepId,p.continuationToken,V)}if(d.status!=="complete")throw new k("Sign-in did not complete. Please try again.");return{accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn}}catch(d){throw d instanceof k?d:I(d,"That code didn't match. Try again.")}}async function U(p){let h;if(t)h=t;else{let c=P();await c.set({accessToken:p,tokenType:"Bearer",expiresIn:3600}),h=$({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:c,autoRefresh:!1})}try{let c=await h.user.me();return kt(c)}catch(c){throw I(c,c instanceof i?`Profile fetch failed (${c.status??"error"})`:"Profile fetch failed")}}return{startPhoneOTP:f,startPhoneOTPForSignIn:R,verifyPhoneOTP:w,fetchProfile:U}}var bt=/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;function Fe(e,t="/"){if(!e)return t;let n=e;try{n=decodeURIComponent(e)}catch{return t}return n.startsWith("/")&&!n.startsWith("//")&&!n.startsWith("/\\")&&!bt.test(n)&&!/^\/+[\\/]/.test(n)?n:t}0&&(module.exports={AuthError,DEFAULT_AUTHORIZE_SCOPE,DEFAULT_TOKEN_STORAGE_KEY,MAX_STORED_TOKEN_BYTES,MFARequiredAuthError,PhoneOtpError,assertValidAuthTokens,createAuthClient,createMemoryTokenStorage,createPhoneOtpClient,deriveCodeChallenge,generateCodeVerifier,generateNonce,generatePkce,generateState,isAuthError,isUnrecoverableAuthError,parseStoredAuthTokens,randomUrlSafeString,safeParseStoredJson,sanitizePostAuthRedirect,serializeAuthTokens,timingSafeEqual,validateStorageKey});
1
+ "use strict";var W=Object.defineProperty;var Je=Object.getOwnPropertyDescriptor;var He=Object.getOwnPropertyNames;var Ve=Object.prototype.hasOwnProperty;var Qe=(e,t)=>{for(var n in t)W(e,n,{get:t[n],enumerable:!0})},We=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of He(t))!Ve.call(e,o)&&o!==n&&W(e,o,{get:()=>t[o],enumerable:!(r=Je(t,o))||r.enumerable});return e};var Ge=e=>We(W({},"__esModule",{value:!0}),e);var vt={};Qe(vt,{AuthContractError:()=>A,AuthError:()=>s,DEFAULT_AUTHORIZE_SCOPE:()=>B,DEFAULT_TOKEN_STORAGE_KEY:()=>Ie,MAX_STORED_TOKEN_BYTES:()=>V,MFARequiredAuthError:()=>v,PhoneOtpError:()=>k,assertValidAuthTokens:()=>I,createAuthClient:()=>N,createMemoryTokenStorage:()=>E,createPhoneOtpClient:()=>Le,deriveCodeChallenge:()=>Z,generateCodeVerifier:()=>X,generateNonce:()=>M,generatePkce:()=>$,generateState:()=>j,isAuthError:()=>q,isUnrecoverableAuthError:()=>de,parseStoredAuthTokens:()=>xe,randomUrlSafeString:()=>D,safeParseStoredJson:()=>De,sanitizePostAuthRedirect:()=>Be,serializeAuthTokens:()=>Me,timingSafeEqual:()=>F,validateStorageKey:()=>je});module.exports=Ge(vt);var s=class extends Error{code;status;details;constructor(t,n,r){super(n),this.name="AuthError",this.code=t,this.status=r?.status,this.details=r?.details}},v=class extends s{mfaMethods;constructor(t,n,r,o){super("mfa_required",t,{status:r,details:o}),this.name="MFARequiredAuthError",this.mfaMethods=n}},A=class extends s{constructor(t,n){super("contract_error",t,{details:n}),this.name="AuthContractError"}};function Ke(e){switch(e){case"mfa_required":case"invalid_request":case"invalid_client":case"invalid_grant":case"unauthorized_client":case"unsupported_grant_type":case"invalid_scope":case"access_denied":case"unsupported_response_type":case"server_error":case"temporarily_unavailable":case"invalid_token":case"insufficient_scope":case"authentication_required":case"insufficient_user_authentication":return e;default:return"unknown_error"}}function Ye(e,t){if(!t)return new s("http_error",`Request failed with status ${e}`,{status:e});let n=Ke(t.error),r=t.error_description??t.reason??(t.error?`Auth error: ${t.error}`:`Request failed with status ${e}`);if(n==="mfa_required"){let o=Array.isArray(t.mfa_methods)?t.mfa_methods.filter(i=>typeof i=="string"):[];return new v(r,o,e,t)}return new s(n,r,{status:e,details:t})}async function ue(e){let t,n=await e.text();if(n)try{t=JSON.parse(n)}catch{t={reason:n}}return Ye(e.status,t)}function q(e){return e instanceof s}function de(e){return q(e)?e.code==="invalid_client"||e.code==="invalid_grant"||e.code==="unauthorized_client"||e.code==="invalid_token":!1}function G(e){if(!Array.isArray(e))return;let t=e.filter(n=>typeof n=="object"&&n!==null&&typeof n.type=="string");return t.length>0?t:void 0}async function l(e){let t=await e.getTokens();if(!t?.accessToken)throw new s("invalid_token","No access token is available. Authenticate first.");return t.accessToken}function y(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>typeof t<"u"))}function b(e,t){let n=e.access_token,r=e.token_type,o=e.expires_in;if(typeof n!="string"||typeof r!="string"||typeof o!="number")throw new s("unknown_error","Unexpected token response payload.",{details:e});let i={accessToken:n,tokenType:r,expiresIn:o},a=typeof e.refresh_token=="string"?e.refresh_token:t;a&&(i.refreshToken=a),typeof e.scope=="string"&&(i.scope=e.scope),typeof e.id_token=="string"&&(i.idToken=e.id_token);let u=G(e.authorization_details);return u&&(i.authorizationDetails=u),i}function Xe(e){return{id:String(e.id??""),deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),browser:typeof e.browser=="string"?e.browser:void 0,os:typeof e.os=="string"?e.os:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0}}function K(e){return{id:String(e.id??""),deviceId:typeof e.device_id=="string"?e.device_id:void 0,deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),userAgent:typeof e.user_agent=="string"?e.user_agent:void 0,browser:typeof e.browser=="string"?e.browser:void 0,browserVersion:typeof e.browser_version=="string"?e.browser_version:void 0,os:typeof e.os=="string"?e.os:void 0,osVersion:typeof e.os_version=="string"?e.os_version:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isRevoked:!!e.is_revoked,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,requiresMfa:!!e.requires_mfa,accessTokenCount:typeof e.access_token_count=="number"?e.access_token_count:0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,expiresAt:typeof e.expires_at=="string"?e.expires_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0,revokedAt:typeof e.revoked_at=="string"?e.revoked_at:void 0,revocationReason:typeof e.revocation_reason=="string"?e.revocation_reason:void 0}}function Y(e){return{success:!!e.success,sessionsRevoked:typeof e.sessions_revoked=="number"?e.sessions_revoked:0,tokensRevoked:typeof e.tokens_revoked=="number"?e.tokens_revoked:0}}function Ze(e){let t=Array.isArray(e.items)?e.items:[],r=e.metadata&&typeof e.metadata=="object"?e.metadata:{};return{items:t.filter(o=>typeof o=="object"&&o!==null).map(Xe),metadata:{page:typeof r.page=="number"?r.page:1,per:typeof r.per=="number"?r.per:t.length,total:typeof r.total=="number"?r.total:t.length}}}function ce(e){return{async list(t){let n=await l(e),r=new URLSearchParams;typeof t?.page=="number"&&r.set("page",String(t.page)),typeof t?.perPage=="number"&&r.set("per_page",String(t.perPage)),t?.userId&&r.set("user_id",t.userId);let o=`/api/v1/sessions${r.size?`?${r.toString()}`:""}`,i=await e.http.request(o,{token:n});return Ze(i)},async current(){let t=await l(e),n=await e.http.request("/api/v1/sessions/current",{token:t});return K(n)},async get(t){let n=await l(e),r=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{token:n});return K(r)},async update(t,n){let r=await l(e),o=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"PATCH",token:r,body:y({device_name:n.deviceName,is_trusted:n.isTrusted})});return K(o)},async revoke(t,n){let r=await l(e),o=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"DELETE",token:r,body:y({reason:n?.reason})});return Y(o)},async revokeAll(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all",{method:"POST",token:t});return Y(n)},async revokeAllDevices(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all-devices",{method:"POST",token:t});return Y(n)}}}function pe(){let e=globalThis.crypto;if(!e?.getRandomValues)throw new s("invalid_request","Web Crypto API is unavailable in this runtime. PKCE requires globalThis.crypto.");return e}function fe(e){let t="";for(let r of e)t+=String.fromCharCode(r);if(typeof btoa!="function")throw new s("server_error","base64UrlEncode requires globalThis.btoa (Web/Deno runtime).");return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function D(e=32){if(!Number.isInteger(e)||e<=0)throw new s("invalid_request","randomUrlSafeString length must be a positive integer.");let t=new Uint8Array(e);return pe().getRandomValues(t),fe(t)}function j(){return D(32)}function M(){return D(32)}function X(){return D(32)}async function Z(e){let t=pe();if(!t.subtle?.digest)throw new s("invalid_request","SubtleCrypto.digest is unavailable; cannot derive an S256 code challenge.");let n=new TextEncoder().encode(e),r=await t.subtle.digest("SHA-256",n);return fe(new Uint8Array(r))}async function $(e="S256"){let t=X();if(e==="plain")return{codeVerifier:t,codeChallenge:t,codeChallengeMethod:"plain"};let n=await Z(t);return{codeVerifier:t,codeChallenge:n,codeChallengeMethod:"S256"}}function F(e,t){let n=new TextEncoder().encode(e),r=new TextEncoder().encode(t),o=Math.max(n.length,r.length),i=n.length^r.length;for(let a=0;a<o;a+=1)i|=(n[a]??0)^(r[a]??0);return i===0}function et(e){return{active:!!e.active,scope:typeof e.scope=="string"?e.scope:void 0,clientId:typeof e.client_id=="string"?e.client_id:void 0,username:typeof e.username=="string"?e.username:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,exp:typeof e.exp=="number"?e.exp:void 0,iat:typeof e.iat=="number"?e.iat:void 0,sub:typeof e.sub=="string"?e.sub:void 0,authorizationDetails:G(e.authorization_details)}}function L(e){return{async password(t){let n=y({grant_type:"password",client_id:e.config.clientId,client_secret:e.config.clientSecret,username:t.username,email:t.email,password:t.password,scope:t.scope,mfa_code:t.mfaCode,mfa_backup_code:t.mfaBackupCode}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o},async refresh(t){let n=await e.getTokens(),r=t?.refreshToken??n?.refreshToken;if(!r)throw new s("invalid_request","No refresh token is available.");let o=y({grant_type:"refresh_token",client_id:e.config.clientId,client_secret:e.config.clientSecret,refresh_token:r,scope:t?.scope}),i=await e.http.request("/oauth/token",{method:"POST",body:o}),a=b(i,r);return await e.setTokens(a),a},async clientCredentials(t){let n=y({grant_type:"client_credentials",client_id:e.config.clientId,client_secret:e.config.clientSecret,scope:t?.scope}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o},async authorizationCode(t){let n=y({grant_type:"authorization_code",client_id:e.config.clientId,client_secret:e.config.clientSecret,code:t.code,redirect_uri:t.redirectUri,code_verifier:t.codeVerifier,scope:t.scope}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o},async revoke(t){let n=await e.getTokens(),r=t?.token??n?.accessToken;if(!r)throw new s("invalid_request","No token provided for revocation.");await e.http.request("/oauth/revoke",{method:"POST",body:y({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:r,token_type_hint:t?.tokenTypeHint})}),n&&(r===n.accessToken||r===n.refreshToken)&&await e.clearTokens()},async introspect(t){let n=await e.http.request("/oauth/introspect",{method:"POST",body:y({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:t.token})});return et(n)},async tokenExchange(t){let n=y({grant_type:"urn:ietf:params:oauth:grant-type:token-exchange",client_id:e.config.clientId,client_secret:e.config.clientSecret,subject_token:t.subjectToken,subject_token_type:t.subjectTokenType??"urn:ietf:params:oauth:token-type:access_token",requested_subject:t.requestedSubject,scope:t.scope,audience:t.audience}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o}}}function le(e,t){let n=e.trim();if(!n)throw new s("invalid_request",`${t} is required.`);return n}async function g(e,t,n){let r=await l(e),o=n?.query,i=o&&Object.keys(o).length>0?`?${new URLSearchParams(Object.entries(o).filter(([,a])=>typeof a<"u").map(([a,u])=>[a,String(u)])).toString()}`:"";return e.http.request(`${t}${i}`,{method:n?.method,body:n?.body,token:r})}async function S(e,t,n){await g(e,t,n)}function C(e,t){return encodeURIComponent(le(e,t))}function tt(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(n=>typeof n=="string"):void 0;return{redirectUri:String(e.redirect_uri??""),code:typeof e.code=="string"?e.code:void 0,state:typeof e.state=="string"?e.state:void 0,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,mfaMethods:t,accessToken:typeof e.access_token=="string"?e.access_token:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,expiresIn:typeof e.expires_in=="number"?e.expires_in:void 0,scope:typeof e.scope=="string"?e.scope:void 0,idToken:typeof e.id_token=="string"?e.id_token:void 0}}function nt(e){let t=Array.isArray(e.redirect_uris)?e.redirect_uris.filter(n=>typeof n=="string"&&n.length>0):[];return{clientId:String(e.client_id??""),name:String(e.name??""),description:typeof e.description=="string"?e.description:void 0,isFirstParty:!!e.is_first_party,redirectUris:t}}function rt(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(r=>typeof r=="string"):void 0,n=Array.isArray(e.uncovered_scopes)?e.uncovered_scopes.filter(r=>typeof r=="string"):void 0;return{consentSatisfied:!!e.consent_satisfied,requiresMfa:!!e.requires_mfa,mfaMethods:t,uncoveredScopes:n,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,code:typeof e.code=="string"?e.code:void 0,redirectUri:typeof e.redirect_uri=="string"?e.redirect_uri:void 0,state:typeof e.state=="string"?e.state:void 0}}function me(e){if(!e.password&&!e.accessToken)throw new s("invalid_request","Either password or accessToken is required for consent.")}function he(e,t){let n=new URL(e),r=new URL(t);if(n.origin!==r.origin||n.pathname!=="/oauth/authorize/consent")throw new s("invalid_request","callbackUrl must target /oauth/authorize/consent on the configured auth server.");return n}function ge(e){async function t(r,o){me(o);let i=he(r,e.config.baseUrl),a={username:o.username,approved:o.approved??!0,requested_scopes:o.requestedScopes,mfa_code:o.mfaCode,mfa_backup_code:o.mfaBackupCode};o.password!==void 0&&(a.password=o.password);let u=await e.http.request(`${i.pathname}${i.search}`,{method:"POST",token:o.accessToken,body:a}),f=tt(u);if(f.error==="mfa_required")throw new v(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}async function n(r,o){me(o);let i=he(r,e.config.baseUrl),a={username:o.username,requested_scopes:o.requestedScopes,mfa_code:o.mfaCode,mfa_backup_code:o.mfaBackupCode};o.password!==void 0&&(a.password=o.password);let u=await e.http.request(`${i.pathname}/evaluate${i.search}`,{method:"POST",token:o.accessToken,body:a}),f=rt(u);if(f.error==="mfa_required"||f.requiresMfa)throw new v(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}return{consent:t,evaluateConsent:n,consentWithCredentials(r){return t(r.callbackUrl,{username:r.username,password:r.password,accessToken:r.accessToken,approved:r.approved,requestedScopes:r.requestedScopes,mfaCode:r.mfaCode,mfaBackupCode:r.mfaBackupCode})},evaluateConsentWithCredentials(r){return n(r.callbackUrl,{username:r.username,password:r.password,accessToken:r.accessToken,requestedScopes:r.requestedScopes,mfaCode:r.mfaCode,mfaBackupCode:r.mfaBackupCode})}}}function ye(e){return{async publicClient(t){let n=await e.http.request(`/oauth/clients/${encodeURIComponent(t)}/public`);return nt(n)},async discoverAuthorizationServer(){let t=await e.http.request("/.well-known/oauth-authorization-server");return{issuer:String(t.issuer??""),authorizationEndpoint:String(t.authorization_endpoint??""),tokenEndpoint:String(t.token_endpoint??""),jwksUri:typeof t.jwks_uri=="string"?t.jwks_uri:void 0,revocationEndpoint:typeof t.revocation_endpoint=="string"?t.revocation_endpoint:void 0,introspectionEndpoint:typeof t.introspection_endpoint=="string"?t.introspection_endpoint:void 0,registrationEndpoint:typeof t.registration_endpoint=="string"?t.registration_endpoint:void 0,scopesSupported:Array.isArray(t.scopes_supported)?t.scopes_supported.filter(n=>typeof n=="string"):void 0,responseTypesSupported:Array.isArray(t.response_types_supported)?t.response_types_supported.filter(n=>typeof n=="string"):[],grantTypesSupported:Array.isArray(t.grant_types_supported)?t.grant_types_supported.filter(n=>typeof n=="string"):void 0,codeChallengeMethodsSupported:Array.isArray(t.code_challenge_methods_supported)?t.code_challenge_methods_supported.filter(n=>typeof n=="string"):void 0,pushedAuthorizationRequestEndpoint:typeof t.pushed_authorization_request_endpoint=="string"?t.pushed_authorization_request_endpoint:void 0,requirePushedAuthorizationRequests:typeof t.require_pushed_authorization_requests=="boolean"?t.require_pushed_authorization_requests:void 0,authorizationDetailsTypesSupported:Array.isArray(t.authorization_details_types_supported)?t.authorization_details_types_supported.filter(n=>typeof n=="string"):void 0,raw:t}}}}var B="openid profile email offline_access",_e=new Set(["response_type","client_id","redirect_uri","scope","state","nonce","code_challenge","code_challenge_method","prompt","login_hint","authorization_details","request_uri"]);function ot(e){if(typeof e=="string"){let t=e.indexOf("?"),n=t>=0?e.slice(t+1):e;return new URLSearchParams(n)}return e instanceof URLSearchParams?e:"raw"in e&&typeof e.raw=="object"?new URLSearchParams(e.raw):new URLSearchParams(e)}function ke(e){let t=ot(e),n={};return t.forEach((r,o)=>{n[o]=r}),{code:t.get("code")??void 0,state:t.get("state")??void 0,error:t.get("error")??void 0,errorDescription:t.get("error_description")??void 0,errorUri:t.get("error_uri")??void 0,raw:n}}function be(e){let t=L(e);return{...ge(e),async createRequest(r){if(!r.redirectUri?.trim())throw new s("invalid_request","redirectUri is required to build an authorization request.");let o=r.scope??B,i=r.state??j(),a=r.nonce??M(),u=await $(r.codeChallengeMethod??"S256"),f=r.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,R=new URL(f),m=R.searchParams;m.set("response_type",r.responseType??"code"),m.set("client_id",e.config.clientId),m.set("redirect_uri",r.redirectUri),m.set("scope",o),m.set("state",i),m.set("nonce",a),m.set("code_challenge",u.codeChallenge),m.set("code_challenge_method",u.codeChallengeMethod),r.authorizationDetails&&r.authorizationDetails.length>0&&m.set("authorization_details",JSON.stringify(r.authorizationDetails)),r.prompt&&m.set("prompt",r.prompt),r.loginHint&&m.set("login_hint",r.loginHint);for(let[w,z]of Object.entries(r.extraParams??{})){if(_e.has(w))throw new s("invalid_request",`extraParams may not override the reserved authorization parameter "${w}".`);m.set(w,z)}return{url:R.toString(),state:i,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:r.redirectUri,scope:o}},async pushAuthorizationRequest(r){if(!r.redirectUri?.trim())throw new s("invalid_request","redirectUri is required to push an authorization request.");let o=r.scope??B,i=r.state??j(),a=r.nonce??M(),u=await $(r.codeChallengeMethod??"S256"),f={response_type:r.responseType??"code",client_id:e.config.clientId,redirect_uri:r.redirectUri,scope:o,state:i,nonce:a,code_challenge:u.codeChallenge,code_challenge_method:u.codeChallengeMethod};e.config.clientSecret&&(f.client_secret=e.config.clientSecret),r.authorizationDetails&&r.authorizationDetails.length>0&&(f.authorization_details=JSON.stringify(r.authorizationDetails));for(let[h,c]of Object.entries(r.extraParams??{})){if(_e.has(h))throw new s("invalid_request",`extraParams may not override the reserved authorization parameter "${h}".`);f[h]=c}let R=await e.http.request("/oauth/par",{method:"POST",body:f}),m=R.request_uri,w=R.expires_in;if(typeof m!="string"||typeof w!="number")throw new s("unknown_error","Unexpected pushed authorization response payload.",{details:R});let z=r.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,p=new URL(z);return p.searchParams.set("client_id",e.config.clientId),p.searchParams.set("request_uri",m),{requestUri:m,expiresIn:w,request:{url:p.toString(),state:i,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:r.redirectUri,scope:o,requestUri:m}}},parseCallback:ke,async probeAuthorize(r){let o=await e.http.requestRaw(r,{headers:{Accept:"application/json"},redirect:"manual"}),i=o.headers.get("location");if(i&&o.status>=300&&o.status<400)return{kind:"redirect",location:i,status:o.status};let a=await o.text(),u=a?JSON.parse(a):{};if(!o.ok)throw new s("server_error",typeof u.error_description=="string"?u.error_description:"Authorization probe failed",{status:o.status,details:u});let f=typeof u.authorization_url=="string"?u.authorization_url:void 0;return{kind:"json",status:o.status,authorizationUrl:f,payload:u}},async handleCallback(r){let i=typeof r.callback=="object"&&!(r.callback instanceof URLSearchParams)&&"raw"in r.callback?r.callback:ke(r.callback);if(i.error)throw new s("access_denied",i.errorDescription??`Authorization failed: ${i.error}`,{details:i.raw});if(!i.state||!F(i.state,r.expectedState))throw new s("invalid_request","State mismatch on authorization callback (possible CSRF).");if(!i.code)throw new s("invalid_request","Authorization callback is missing the `code` parameter.");return t.authorizationCode({code:i.code,redirectUri:r.redirectUri,codeVerifier:r.codeVerifier,scope:r.scope})}}}function O(e){let t=e.step_id,n=e.step_type,r=e.name,o=e.order,i=e.is_required,a=e.timeout;if(typeof t!="string"||typeof n!="string"||typeof r!="string"||typeof o!="number"||typeof i!="boolean"||typeof a!="number")throw new s("unknown_error","Unexpected flow step payload.",{details:e});return{stepId:t,stepType:n,name:r,description:typeof e.description=="string"?e.description:void 0,order:o,isRequired:i,timeout:a,inputSchema:e.input_schema&&typeof e.input_schema=="object"?e.input_schema:void 0}}function ee(e){let t=e.current_step,n=e.remaining_steps;if(!t||typeof t!="object")throw new s("unknown_error","Missing current_step in flow response.",{details:e});let r=e.continuation_token;if(typeof r!="string"||!r)throw new s("unknown_error","Missing continuation_token in flow response.",{details:e});return{sessionId:String(e.session_id??""),flowId:String(e.flow_id??""),flowName:String(e.flow_name??""),currentStep:O(t),remainingSteps:Array.isArray(n)?n.filter(o=>typeof o=="object"&&o!==null).map(O):[],expiresAt:String(e.expires_at??""),continuationToken:r}}function it(e){return{sessionId:String(e.session_id??""),status:String(e.status??""),purpose:String(e.purpose??""),currentStep:e.current_step&&typeof e.current_step=="object"?O(e.current_step):void 0,completedSteps:Array.isArray(e.completed_steps)?e.completed_steps.filter(t=>typeof t=="string"):[],remainingSteps:Array.isArray(e.remaining_steps)?e.remaining_steps.filter(t=>typeof t=="object"&&t!==null).map(O):[],failedAttempts:typeof e.failed_attempts=="number"?e.failed_attempts:0,expiresAt:String(e.expires_at??""),lastActivityAt:String(e.last_activity_at??"")}}async function te(e,t){let n=t.status;if(n==="error"||typeof t.error=="string"&&n!=="in_progress"&&n!=="complete")throw new s("invalid_request",typeof t.error=="string"?t.error:"Flow step failed.",{details:t});if(n==="in_progress"){let r=t.next_step,o=t.remaining_steps;if(!r||typeof r!="object")throw new s("unknown_error","Missing next_step in flow step response.",{details:t});let i=t.debug&&typeof t.debug=="object"&&!Array.isArray(t.debug)?t.debug:void 0;return{status:"in_progress",sessionId:String(t.session_id??""),nextStep:O(r),completedSteps:Array.isArray(t.completed_steps)?t.completed_steps.filter(u=>typeof u=="string"):[],remainingSteps:Array.isArray(o)?o.filter(u=>typeof u=="object"&&u!==null).map(O):[],debug:i}}if(n==="complete"){let r=b(t);return await e.setTokens(r),{status:"complete",accessToken:r.accessToken,refreshToken:r.refreshToken,tokenType:r.tokenType,expiresIn:r.expiresIn,scope:r.scope,amr:Array.isArray(t.amr)?t.amr.filter(i=>typeof i=="string"):[],acr:typeof t.acr=="string"?t.acr:""}}throw new s("unknown_error","Unknown flow step status.",{details:t})}function Re(e){return{async initAuthentication(t){let n=await e.http.request("/oauth/authenticate/init",{method:"POST",body:y({client_id:t?.clientId??e.config.clientId,username:t?.username,flow_type:t?.flowType})});return ee(n)},async executeStep(t){let n=await e.http.request("/oauth/authenticate/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return te(e,n)},async initRegistration(t){let n=await e.http.request("/oauth/register/init",{method:"POST",body:y({client_id:t?.clientId??e.config.clientId,invite_code:t?.inviteCode,flow_type:t?.flowType})});return ee(n)},async executeRegistrationStep(t){let n=await e.http.request("/oauth/register/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return te(e,n)},async getStatus(t,n){let r=new URLSearchParams({continuation_token:n}),o=await e.http.request(`/oauth/flow/status/${encodeURIComponent(t)}?${r}`);return it(o)},async initRecovery(t){let n=await e.http.request("/oauth/recovery/init",{method:"POST",body:y({client_id:t?.clientId??e.config.clientId,recovery_type:t?.recoveryType,redirect_uri:t?.redirectUri})});return ee(n)},async executeRecoveryStep(t){let n=await e.http.request("/oauth/recovery/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return te(e,n)}}}function J(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function st(e){return{issuer:String(e.issuer??""),authorizationEndpoint:String(e.authorization_endpoint??""),tokenEndpoint:String(e.token_endpoint??""),userinfoEndpoint:typeof e.userinfo_endpoint=="string"?e.userinfo_endpoint:void 0,jwksUri:String(e.jwks_uri??""),revocationEndpoint:typeof e.revocation_endpoint=="string"?e.revocation_endpoint:void 0,introspectionEndpoint:typeof e.introspection_endpoint=="string"?e.introspection_endpoint:void 0,responseTypesSupported:J(e.response_types_supported),grantTypesSupported:J(e.grant_types_supported),scopesSupported:J(e.scopes_supported),codeChallengeMethodsSupported:J(e.code_challenge_methods_supported),raw:e}}function at(e){return{sub:String(e.sub??""),name:typeof e.name=="string"?e.name:void 0,givenName:typeof e.given_name=="string"?e.given_name:void 0,familyName:typeof e.family_name=="string"?e.family_name:void 0,middleName:typeof e.middle_name=="string"?e.middle_name:void 0,nickname:typeof e.nickname=="string"?e.nickname:void 0,preferredUsername:typeof e.preferred_username=="string"?e.preferred_username:void 0,profile:typeof e.profile=="string"?e.profile:void 0,picture:typeof e.picture=="string"?e.picture:void 0,website:typeof e.website=="string"?e.website:void 0,gender:typeof e.gender=="string"?e.gender:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0,zoneinfo:typeof e.zoneinfo=="string"?e.zoneinfo:void 0,locale:typeof e.locale=="string"?e.locale:void 0,updatedAt:typeof e.updated_at=="number"?e.updated_at:void 0,email:typeof e.email=="string"?e.email:void 0,emailVerified:typeof e.email_verified=="boolean"?e.email_verified:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,phoneNumberVerified:typeof e.phone_number_verified=="boolean"?e.phone_number_verified:void 0}}function we(e){return{async userInfo(){let t=await l(e),n=await e.http.request("/oauth/userinfo",{token:t});return at(n)},async discover(){let t=await e.http.request("/.well-known/openid-configuration");return st(t)},async jwks(){let t=await e.http.request("/oauth/jwks");return{keys:Array.isArray(t.keys)?t.keys.filter(r=>typeof r=="object"&&r!==null):[]}}}}function H(e){return{...e,id:typeof e.id=="string"?e.id:"",organizationId:typeof e.organization_id=="string"?e.organization_id:void 0,email:typeof e.email=="string"?e.email:void 0,emailVerified:typeof e.email_verified=="boolean"?e.email_verified:void 0,username:typeof e.username=="string"?e.username:void 0,firstName:typeof e.first_name=="string"?e.first_name:void 0,lastName:typeof e.last_name=="string"?e.last_name:void 0,isActive:typeof e.is_active=="boolean"?e.is_active:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0,mfaEnabled:typeof e.mfa_enabled=="boolean"?e.mfa_enabled:void 0}}function ve(e){if(typeof e!="object"||e===null||Array.isArray(e))throw new A("Malformed primary-email verification response.",e);let t=e,n=t.status,r=t.email,o=t.email_verified;if(!((n==="sent"||n==="verified")&&typeof r=="string"&&r.length>0&&typeof o=="boolean"&&(n==="sent"&&o===!1||n==="verified"&&o===!0)))throw new A("Malformed primary-email verification response.",t);return{status:n,email:r,emailVerified:o}}function ne(e){return{id:String(e.id??""),name:typeof e.name=="string"?e.name:void 0,email:typeof e.email=="string"?e.email:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,relationship:typeof e.relationship=="string"?e.relationship:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0}}function ut(e){return{id:String(e.id??""),provider:String(e.provider??""),providerUserId:typeof e.provider_user_id=="string"?e.provider_user_id:void 0,email:typeof e.email=="string"?e.email:void 0,isPrimary:typeof e.is_primary=="boolean"?e.is_primary:void 0}}function Se(e){return dt(e)}function dt(e){return{async me(){let t=await l(e),n=await e.http.request("/api/v1/users/me",{token:t});return H(n)},async updateMe(t){let n=await g(e,"/api/v1/users/me",{method:"PATCH",body:t});return H(n)},emailVerification:{async start(t){let n=await g(e,"/api/v1/users/me/email/verify",{method:"POST",body:{email:t.email}});return ve(n)},async verify(t){let n=await g(e,"/api/v1/users/me/email/verify",{method:"POST",body:{code:t.code}});return ve(n)}},async changePassword(t){await S(e,"/api/v1/users/me/password",{method:"POST",body:{current_password:t.currentPassword,new_password:t.newPassword}})},async deleteAvatar(){let t=await g(e,"/api/v1/users/me/avatar",{method:"DELETE"});return H(t)},async uploadAvatar(t,n="avatar.jpg"){let r=await l(e),o=new FormData,i=t instanceof Blob?t:new Blob([new Uint8Array(t)]);o.append("avatar",i,n);let a=await e.http.request("/api/v1/users/me/avatar",{method:"POST",token:r,body:o});return H(a)},async verifyPhone(t){return g(e,"/api/v1/users/me/phone/verify",{method:"POST",body:t})},async verifyRecoveryEmail(t){return g(e,"/api/v1/users/me/recovery-email/verify",{method:"POST",body:t})},async securityOverview(){return g(e,"/api/v1/users/me/security-overview")},recoveryContacts:{async list(){let t=await g(e,"/api/v1/users/me/recovery-contacts");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(ne):[]},async create(t){let n=await g(e,"/api/v1/users/me/recovery-contacts",{method:"POST",body:t});return ne(n)},async update(t,n){let r=await g(e,`/api/v1/users/me/recovery-contacts/${C(t,"contactId")}`,{method:"PATCH",body:n});return ne(r)},async delete(t){await S(e,`/api/v1/users/me/recovery-contacts/${C(t,"contactId")}`,{method:"DELETE"})}},identities:{async list(){let t=await g(e,"/api/v1/users/me/identities");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(ut):[]},async unlink(t){await S(e,`/api/v1/users/me/identities/${C(t,"identityId")}`,{method:"DELETE"})},async setPrimary(t){return g(e,`/api/v1/users/me/identities/${C(t,"identityId")}/primary`,{method:"PATCH"})}},async deleteMe(t){await S(e,"/api/v1/users/me",{method:"DELETE",body:{password:t.password}})}}}function P(e){return e&&typeof e=="object"?e:{}}function Te(e){return{async registerBegin(t){let n=await l(e),r=await e.http.request("/api/v1/users/me/webauthn/register/begin",{method:"POST",token:n,body:t});return P(r)},async registerFinish(t){let n=await l(e),r=await e.http.request("/api/v1/users/me/webauthn/register/finish",{method:"POST",token:n,body:t});return P(r)},async authenticateBegin(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/begin",{method:"POST",body:t});return P(n)},async authenticateFinish(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/finish",{method:"POST",body:t}),r=P(n);if(typeof r.access_token=="string"){let o=b(r);await e.setTokens(o)}return r},async credentials(){let t=await l(e),n=await e.http.request("/api/v1/users/me/webauthn/credentials",{token:t});return P(n)},async removeCredential(t,n){let r=await l(e);await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}`,{method:"DELETE",token:r,body:n?.password?{password:n.password}:void 0})},async renameCredential(t,n){let r=await l(e),o=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/rename`,{method:"PATCH",token:r,body:n});return P(o)},async setPrimaryCredential(t){let n=await l(e),r=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/primary`,{method:"POST",token:n});return P(r)}}}function ct(e){return{isActive:!!(e.is_active??e.isActive),message:typeof e.message=="string"?e.message:void 0,scheduledStart:typeof e.scheduled_start=="string"?e.scheduled_start:void 0,scheduledEnd:typeof e.scheduled_end=="string"?e.scheduled_end:void 0,...e}}function Ae(e){return{async status(){let t=await e.http.request("/api/v1/maintenance/status");return ct(t)}}}var pt=128,re=254;function T(e,t){if(typeof e!="string")return;let n=e.trim();if(!(!n||n.length>t))return n}function Ce(e){return{async request(t){let n=y({email:T(t.email,re),identifier:T(t.identifier,re),recovery_email:T(t.recoveryEmail,re),phone_number:T(t.phoneNumber,32),member_id:T(t.memberId,64),security_question:T(t.securityQuestion,256),security_answer:T(t.securityAnswer,256),redirect_uri:T(t.redirectUri,2048)}),r=await e.http.request("/oauth/password/reset/request",{method:"POST",body:n});return{ok:!!r.ok,message:String(r.message??"")}},async validate(t){let n=t.trim();if(!n)throw new s("invalid_request","token is required.");let r=await e.http.request(`/oauth/password/reset/validate?token=${encodeURIComponent(n)}`);return{ok:!!r.ok,valid:!!r.valid,expiresAt:typeof r.expires_at=="string"?r.expires_at:void 0}},async complete(t){if(!t.token.trim())throw new s("invalid_request","token is required.");if(!t.password||t.password.length>pt)throw new s("invalid_request","password is required and must be <= 128 characters.");let n=await e.http.request("/oauth/password/reset/complete",{method:"POST",body:{token:t.token.trim(),password:t.password,password_confirm:t.passwordConfirm}});return{ok:!!n.ok,message:String(n.message??"")}}}}function ft(e){return{id:String(e.id??""),deviceName:String(e.device_name??""),isVerified:!!e.is_verified,isPrimary:!!e.is_primary,createdAt:typeof e.created_at=="string"?e.created_at:void 0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0}}function Pe(e){return{async setup(t){let n=t.deviceName?.trim();if(!n||n.length>128)throw new s("invalid_request","deviceName is required.");let r=await g(e,"/api/v1/users/me/mfa/setup",{method:"POST",body:{device_name:n}});return{deviceId:String(r.device_id??""),secret:String(r.secret??""),qrCodeUri:String(r.qr_code_uri??""),backupCodes:Array.isArray(r.backup_codes)?r.backup_codes.filter(o=>typeof o=="string"):[],algorithm:String(r.algorithm??""),digits:typeof r.digits=="number"?r.digits:6,period:typeof r.period=="number"?r.period:30}},async verify(t){return g(e,"/api/v1/users/me/mfa/verify",{method:"POST",body:{device_id:t.deviceId,totp_code:t.totpCode}})},async devices(){let t=await g(e,"/api/v1/users/me/mfa/devices");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(ft):[]},async removeDevice(t){await S(e,`/api/v1/users/me/mfa/devices/${C(t,"deviceId")}`,{method:"DELETE"})},async regenerateBackupCodes(){let t=await g(e,"/api/v1/users/me/mfa/backup-codes/regenerate",{method:"POST"});return{backupCodes:Array.isArray(t.backup_codes)?t.backup_codes.filter(n=>typeof n=="string"):[]}},async disable(t){await S(e,"/api/v1/users/me/mfa/disable",{method:"POST",body:y({password:t?.password})})}}}var Ee="https://prod-auth.tktchurch.com",lt=new Set(["localhost","127.0.0.1","[::1]"]);function mt(e){return lt.has(e.toLowerCase())}function oe(e,t={}){let n=(e??Ee).trim();if(!n)return oe(Ee,t);let o=(/^https?:\/\//i.test(n)?n:`https://${n}`).replace(/\/+$/,""),i;try{i=new URL(o)}catch{throw new s("invalid_request","baseUrl must be a valid absolute URL.")}if(i.protocol==="http:"&&!t.allowInsecureTransport&&!mt(i.hostname))throw new s("invalid_request","baseUrl must use HTTPS. Set allowInsecureTransport=true only for trusted local development.");return o}function ht(e,t){if(!e&&t<=0)return{cleanup:()=>{}};let n=new AbortController,r,o=()=>{n.abort(e?.reason)};return e&&(e.aborted?n.abort(e.reason):e.addEventListener("abort",o,{once:!0})),t>0&&(r=setTimeout(()=>{n.abort(new Error(`Request timed out after ${t}ms`))},t)),{signal:n.signal,cleanup:()=>{r&&clearTimeout(r),e&&e.removeEventListener("abort",o)}}}function gt(e,t){return/^https?:\/\//i.test(t)?t:`${e}${t.startsWith("/")?t:`/${t}`}`}function yt(e,t,n){let r=new Headers(e);return t&&new Headers(t).forEach((i,a)=>{r.set(a,i)}),n&&!r.has("Authorization")&&r.set("Authorization",`Bearer ${n}`),r}function qe(e){return{async request(t,n){let r=await this.requestRaw(t,n);if(!r.ok)throw await ue(r);if(r.status===204)return;let o=await r.text();if(o)return JSON.parse(o)},async requestRaw(t,n){let r=gt(e.baseUrl,t),o=yt(e.defaultHeaders,n?.headers,n?.token),{signal:i,cleanup:a}=ht(n?.signal,e.timeoutMs),u={method:n?.method??"GET",headers:o,signal:i,redirect:n?.redirect};typeof n?.body<"u"&&(n.body instanceof FormData?u.body=n.body:(o.has("Content-Type")||o.set("Content-Type","application/json"),u.body=JSON.stringify(n.body)));try{return await e.fetch(r,u)}catch(f){throw i?.aborted??!1?new s("timeout",`Request timed out: ${r}`,{details:f}):new s("network_error",`Network request failed: ${r}`,{details:f})}finally{a()}}}}var Ie="@tktchurch/auth/tokens",V=32768,Ue=new Set(["accessToken","tokenType","expiresIn","refreshToken","scope","idToken","authorizationDetails"]),ze=new Set(["__proto__","constructor","prototype"]),_t=/^[\w@./:-]{1,128}$/;function se(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Oe(e){return typeof e=="string"&&e.length>0}function ie(e){return typeof e=="string"&&e.length>0?e:void 0}function I(e){if(!se(e))throw new s("invalid_request","Token storage rejected a non-object token payload.");for(let i of Object.keys(e))if(!Ue.has(i))throw new s("invalid_request",`Token storage rejected unknown field "${i}".`);if(!Oe(e.accessToken))throw new s("invalid_request","Token storage requires a non-empty accessToken.");if(!Oe(e.tokenType))throw new s("invalid_request","Token storage requires a non-empty tokenType.");if(typeof e.expiresIn!="number"||!Number.isFinite(e.expiresIn)||e.expiresIn<0)throw new s("invalid_request","Token storage requires a non-negative numeric expiresIn.");let t={accessToken:e.accessToken,tokenType:e.tokenType,expiresIn:e.expiresIn},n=ie(e.refreshToken);n&&(t.refreshToken=n);let r=ie(e.scope);r&&(t.scope=r);let o=ie(e.idToken);if(o&&(t.idToken=o),typeof e.authorizationDetails<"u"){if(!Array.isArray(e.authorizationDetails)||!e.authorizationDetails.every(i=>se(i)&&typeof i.type=="string"))throw new s("invalid_request","Token storage rejected malformed authorizationDetails.");t.authorizationDetails=e.authorizationDetails}return t}function xe(e){if(!se(e))return null;for(let t of Object.keys(e))if(ze.has(t)||!Ue.has(t))return null;try{return I(e)}catch{return null}}function De(e){return JSON.parse(e,(t,n)=>{if(ze.has(t))throw new SyntaxError("Forbidden JSON key in stored token payload.");return n})}function je(e){let t=e.trim();if(!t)throw new s("invalid_request","Token storage key must be a non-empty string.");if(!_t.test(t))throw new s("invalid_request","Token storage key contains unsupported characters or exceeds 128 characters.");return t}function Me(e){let t=I(e),n=JSON.stringify(t);if(n.length>V)throw new s("invalid_request",`Serialized token payload exceeds ${V} bytes.`);return n}var ae=class{state=null;get(){return this.state}set(t){if(!t){this.clear();return}this.state=I(t)}clear(){this.state=null}};function E(){return new ae}function kt(){return typeof window<"u"&&typeof window.document<"u"}function bt(e){if(e)return e;if(typeof globalThis.fetch=="function")return globalThis.fetch.bind(globalThis);throw new s("invalid_request","No fetch implementation available. Provide config.fetch.")}function $e(e){if(!e.clientId?.trim())throw new s("invalid_request","clientId is required.");if(kt()&&e.clientSecret&&!e.allowClientSecretInBrowser)throw new s("invalid_request","clientSecret in browser runtime is blocked by default. Set allowClientSecretInBrowser=true to override.");return{clientId:e.clientId,clientSecret:e.clientSecret,baseUrl:oe(e.baseUrl,{allowInsecureTransport:e.allowInsecureTransport??!1}),fetch:bt(e.fetch),storage:e.storage??E(),timeoutMs:e.timeoutMs??15e3,defaultHeaders:e.defaultHeaders??{},autoRefresh:e.autoRefresh??!0,allowClientSecretInBrowser:e.allowClientSecretInBrowser??!1,allowInsecureTransport:e.allowInsecureTransport??!1}}function N(e){let t=$e(e),n=qe({baseUrl:t.baseUrl,fetch:t.fetch,timeoutMs:t.timeoutMs,defaultHeaders:t.defaultHeaders}),r=async()=>await t.storage.get(),o=async u=>{await t.storage.set(u)},i=async()=>{await t.storage.clear()},a={config:t,http:n,getTokens:r,setTokens:o,clearTokens:i};return{token:L(a),flow:Re(a),oidc:we(a),authorize:be(a),user:Se(a),sessions:ce(a),webauthn:Te(a),passwordReset:Ce(a),mfa:Pe(a),maintenance:Ae(a),oauth:ye(a),tokens:{get:r,set:o,clear:i}}}var k=class extends Error{name="PhoneOtpError"};function U(e,t){return e instanceof k?e:q(e)?new k(e.message||t):e instanceof Error&&e.message?new k(e.message):new k(t)}function Ne(e){if(!q(e)||typeof e.status!="number")return!1;let t=e.status;return t>=400&&t<500&&t!==429}function Fe(e){if(e.status!=="in_progress"||!e.debug)return;let t=e.debug.verification_code;return typeof t=="string"?t:void 0}function Rt(e){return{...e,id:typeof e.id=="string"?e.id:"",first_name:typeof e.first_name=="string"?e.first_name:typeof e.firstName=="string"?e.firstName:void 0,last_name:typeof e.last_name=="string"?e.last_name:typeof e.lastName=="string"?e.lastName:void 0,email:typeof e.email=="string"?e.email:void 0,phone_number:typeof e.phone_number=="string"?e.phone_number:typeof e.phoneNumber=="string"?e.phoneNumber:void 0,phone_country_code:typeof e.phone_country_code=="string"?e.phone_country_code:typeof e.phoneCountryCode=="string"?e.phoneCountryCode:void 0,phone_verified:typeof e.phone_verified=="boolean"?e.phone_verified:typeof e.phoneVerified=="boolean"?e.phoneVerified:void 0,profile_picture_url:typeof e.profile_picture_url=="string"?e.profile_picture_url:typeof e.profilePictureUrl=="string"?e.profilePictureUrl:void 0,picture:typeof e.picture=="string"?e.picture:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0}}function Le(e){let t=e.auth,n=e.guestProfile??{firstName:"Guest",lastName:"User"},r=n.emailDomain??"registrations.tktchurch.local",o=n.emailLocalPrefix??"reg";function i(){return t||N({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:E(),autoRefresh:!1})}async function a(p,h){let c=i(),d=await c.flow.initAuthentication({flowType:"phone_only",username:h}),_=await c.flow.executeStep({sessionId:d.sessionId,stepId:d.currentStep.stepId,continuationToken:d.continuationToken,credential:p});if(_.status!=="in_progress")throw new k("Unexpected sign-in response.");return{oauthSessionId:d.sessionId,verifyStepId:_.nextStep.stepId,mode:"authentication",continuationToken:d.continuationToken,debugCode:Fe(_)}}async function u(p){let h=i(),c=await h.flow.initRegistration({flowType:"phone_registration"}),d=await h.flow.executeRegistrationStep({sessionId:c.sessionId,stepId:c.currentStep.stepId,continuationToken:c.continuationToken,credential:p});if(d.status!=="in_progress")throw new k("Unexpected verification response.");return{oauthSessionId:c.sessionId,verifyStepId:d.nextStep.stepId,mode:"registration",continuationToken:c.continuationToken,debugCode:Fe(d)}}async function f(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await u(d)}catch(_){if(!Ne(_))throw U(_,"Could not send the code. Please try again.");try{return await a(d,c)}catch{throw U(_,"Could not send the code. Please try again.")}}}async function R(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await a(d,c)}catch(_){if(!Ne(_))throw U(_,"Could not start sign-in.");try{return await u(d)}catch{throw U(_,"Could not start sign-in.")}}}async function m(p,h,c,d,_,x){return h==="registration"?await p.flow.executeRegistrationStep({sessionId:c,stepId:d,continuationToken:_,credential:x}):await p.flow.executeStep({sessionId:c,stepId:d,continuationToken:_,credential:x})}async function w(p,h){let c=i();try{let d=await m(c,p.mode,p.oauthSessionId,p.verifyStepId,p.continuationToken,{code:h}),_=0;for(;d.status==="in_progress"&&_<6;){_++;let x=d.nextStep.stepType,Q={};x==="profile_info"?Q={first_name:n.firstName,last_name:n.lastName,email:`${o}+${p.oauthSessionId.slice(0,8).toLowerCase()}@${r}`}:x==="terms_acceptance"&&(Q={accepted:"true"}),d=await m(c,p.mode,p.oauthSessionId,d.nextStep.stepId,p.continuationToken,Q)}if(d.status!=="complete")throw new k("Sign-in did not complete. Please try again.");return{accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn}}catch(d){throw d instanceof k?d:U(d,"That code didn't match. Try again.")}}async function z(p){let h;if(t)h=t;else{let c=E();await c.set({accessToken:p,tokenType:"Bearer",expiresIn:3600}),h=N({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:c,autoRefresh:!1})}try{let c=await h.user.me();return Rt(c)}catch(c){throw U(c,c instanceof s?`Profile fetch failed (${c.status??"error"})`:"Profile fetch failed")}}return{startPhoneOTP:f,startPhoneOTPForSignIn:R,verifyPhoneOTP:w,fetchProfile:z}}var wt=/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;function Be(e,t="/"){if(!e)return t;let n=e;try{n=decodeURIComponent(e)}catch{return t}return n.startsWith("/")&&!n.startsWith("//")&&!n.startsWith("/\\")&&!wt.test(n)&&!/^\/+[\\/]/.test(n)?n:t}0&&(module.exports={AuthContractError,AuthError,DEFAULT_AUTHORIZE_SCOPE,DEFAULT_TOKEN_STORAGE_KEY,MAX_STORED_TOKEN_BYTES,MFARequiredAuthError,PhoneOtpError,assertValidAuthTokens,createAuthClient,createMemoryTokenStorage,createPhoneOtpClient,deriveCodeChallenge,generateCodeVerifier,generateNonce,generatePkce,generateState,isAuthError,isUnrecoverableAuthError,parseStoredAuthTokens,randomUrlSafeString,safeParseStoredJson,sanitizePostAuthRedirect,serializeAuthTokens,timingSafeEqual,validateStorageKey});
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AuthClientConfig, C as ConsumerAuthClient, a as AuthClient, b as AuthTokens } from './memory-CSq_KMM2.cjs';
2
- export { c as AuthorizationCodeTokenRequest, d as AuthorizationConsentBody, e as AuthorizationConsentResponse, f as AuthorizationDetail, g as AuthorizationProbeResult, h as AuthorizationRequest, i as AuthorizationUrlOptions, j as AuthorizeEndpoints, k as CallbackParams, l as ClientCredentialsRequest, m as ConsumerMaintenanceEndpoints, n as ConsumerUserEndpoints, E as ExecuteStepRequest, F as FlowEndpoints, o as FlowInitResponse, p as FlowSessionStatus, q as FlowStep, r as FlowStepCompleteResult, s as FlowStepInProgressResult, t as FlowStepResult, H as HandleCallbackOptions, I as InitAuthenticationRequest, u as InitRegistrationRequest, v as IntrospectTokenRequest, M as MaintenanceStatus, w as MfaDevice, x as MfaEndpoints, O as OAuthAuthorizationServerMetadata, y as OAuthMetaEndpoints, z as OidcDiscoveryDocument, B as OidcEndpoints, P as PageQuery, D as PageResponse, G as PasswordResetEndpoints, J as PasswordTokenRequest, K as PublicClientInfo, L as PushAuthorizationRequestOptions, N as PushedAuthorizationResult, R as RefreshTokenRequest, Q as RevocationResponse, S as RevokeSessionRequest, T as RevokeTokenRequest, U as SessionDetail, V as SessionEndpoints, W as SessionListQuery, X as SessionSummary, Y as TokenEndpoints, Z as TokenExchangeRequest, _ as TokenIntrospectionResponse, $ as TokenStorage, a0 as UpdateSessionRequest, a1 as UserEndpoints, a2 as UserInfoResponse, a3 as UserProfile, a4 as WebAuthnEndpoints, a5 as createMemoryTokenStorage } from './memory-CSq_KMM2.cjs';
1
+ import { A as AuthClientConfig, C as ConsumerAuthClient, a as AuthClient, b as AuthTokens } from './memory-DCHtjktX.cjs';
2
+ export { c as AuthorizationCodeTokenRequest, d as AuthorizationConsentBody, e as AuthorizationConsentResponse, f as AuthorizationDetail, g as AuthorizationProbeResult, h as AuthorizationRequest, i as AuthorizationUrlOptions, j as AuthorizeEndpoints, k as CallbackParams, l as ClientCredentialsRequest, m as ConsumerMaintenanceEndpoints, n as ConsumerUserEndpoints, E as EmailVerificationResponse, o as ExecuteStepRequest, F as FlowEndpoints, p as FlowInitResponse, q as FlowSessionStatus, r as FlowStep, s as FlowStepCompleteResult, t as FlowStepInProgressResult, u as FlowStepResult, H as HandleCallbackOptions, I as InitAuthenticationRequest, v as InitRegistrationRequest, w as IntrospectTokenRequest, M as MaintenanceStatus, x as MfaDevice, y as MfaEndpoints, O as OAuthAuthorizationServerMetadata, z as OAuthMetaEndpoints, B as OidcDiscoveryDocument, D as OidcEndpoints, P as PageQuery, G as PageResponse, J as PasswordResetEndpoints, K as PasswordTokenRequest, L as PublicClientInfo, N as PushAuthorizationRequestOptions, Q as PushedAuthorizationResult, R as RefreshTokenRequest, S as RevocationResponse, T as RevokeSessionRequest, U as RevokeTokenRequest, V as SessionDetail, W as SessionEndpoints, X as SessionListQuery, Y as SessionSummary, Z as StartEmailVerificationRequest, _ as TokenEndpoints, $ as TokenExchangeRequest, a0 as TokenIntrospectionResponse, a1 as TokenStorage, a2 as UpdateSessionRequest, a3 as UserEndpoints, a4 as UserInfoResponse, a5 as UserProfile, a6 as VerifyEmailVerificationRequest, a7 as WebAuthnEndpoints, a8 as createMemoryTokenStorage } from './memory-DCHtjktX.cjs';
3
3
 
4
4
  /**
5
5
  * Creates a consumer-only auth client for public npm distribution.
@@ -107,7 +107,7 @@ declare function validateStorageKey(key: string): string;
107
107
  declare function serializeAuthTokens(tokens: AuthTokens): string;
108
108
 
109
109
  /** Supported normalized auth error codes returned by the SDK. */
110
- type AuthErrorCode = "mfa_required" | "invalid_request" | "invalid_client" | "invalid_grant" | "unauthorized_client" | "unsupported_grant_type" | "invalid_scope" | "access_denied" | "unsupported_response_type" | "server_error" | "temporarily_unavailable" | "invalid_token" | "insufficient_scope" | "authentication_required" | "insufficient_user_authentication" | "http_error" | "network_error" | "timeout" | "unknown_error";
110
+ type AuthErrorCode = "mfa_required" | "invalid_request" | "invalid_client" | "invalid_grant" | "unauthorized_client" | "unsupported_grant_type" | "invalid_scope" | "access_denied" | "unsupported_response_type" | "server_error" | "temporarily_unavailable" | "invalid_token" | "insufficient_scope" | "authentication_required" | "insufficient_user_authentication" | "http_error" | "network_error" | "timeout" | "contract_error" | "unknown_error";
111
111
  /** Base SDK error type for HTTP, OAuth, and transport failures. */
112
112
  declare class AuthError extends Error {
113
113
  readonly code: AuthErrorCode;
@@ -123,6 +123,10 @@ declare class MFARequiredAuthError extends AuthError {
123
123
  readonly mfaMethods: string[];
124
124
  constructor(message: string, mfaMethods: string[], status?: number, details?: unknown);
125
125
  }
126
+ /** The server returned a successful HTTP status with an invalid response body. */
127
+ declare class AuthContractError extends AuthError {
128
+ constructor(message: string, details?: unknown);
129
+ }
126
130
  /** Type guard for SDK errors. */
127
131
  declare function isAuthError(error: unknown): error is AuthError;
128
132
  /** Returns true for errors that should clear local token state. */
@@ -180,4 +184,4 @@ declare function sanitizePostAuthRedirect(value?: string | null, fallback?: stri
180
184
  /** Default OIDC scope set covering identity claims plus refresh capability. */
181
185
  declare const DEFAULT_AUTHORIZE_SCOPE = "openid profile email offline_access";
182
186
 
183
- export { ConsumerAuthClient as AuthClient, AuthClientConfig, AuthError, type AuthErrorCode, AuthTokens, type CodeChallengeMethod, ConsumerAuthClient, DEFAULT_AUTHORIZE_SCOPE, DEFAULT_TOKEN_STORAGE_KEY, MAX_STORED_TOKEN_BYTES, MFARequiredAuthError, type PhoneOtpClient, type PhoneOtpClientConfig, PhoneOtpError, type PhoneOtpFlowMode, type PhoneOtpGuestProfile, type PhoneOtpProfile, type PhoneOtpStart, type PhoneOtpTokens, type PkcePair, assertValidAuthTokens, createAuthClient, createPhoneOtpClient, deriveCodeChallenge, generateCodeVerifier, generateNonce, generatePkce, generateState, isAuthError, isUnrecoverableAuthError, parseStoredAuthTokens, randomUrlSafeString, safeParseStoredJson, sanitizePostAuthRedirect, serializeAuthTokens, timingSafeEqual, validateStorageKey };
187
+ export { ConsumerAuthClient as AuthClient, AuthClientConfig, AuthContractError, AuthError, type AuthErrorCode, AuthTokens, type CodeChallengeMethod, ConsumerAuthClient, DEFAULT_AUTHORIZE_SCOPE, DEFAULT_TOKEN_STORAGE_KEY, MAX_STORED_TOKEN_BYTES, MFARequiredAuthError, type PhoneOtpClient, type PhoneOtpClientConfig, PhoneOtpError, type PhoneOtpFlowMode, type PhoneOtpGuestProfile, type PhoneOtpProfile, type PhoneOtpStart, type PhoneOtpTokens, type PkcePair, assertValidAuthTokens, createAuthClient, createPhoneOtpClient, deriveCodeChallenge, generateCodeVerifier, generateNonce, generatePkce, generateState, isAuthError, isUnrecoverableAuthError, parseStoredAuthTokens, randomUrlSafeString, safeParseStoredJson, sanitizePostAuthRedirect, serializeAuthTokens, timingSafeEqual, validateStorageKey };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AuthClientConfig, C as ConsumerAuthClient, a as AuthClient, b as AuthTokens } from './memory-CSq_KMM2.js';
2
- export { c as AuthorizationCodeTokenRequest, d as AuthorizationConsentBody, e as AuthorizationConsentResponse, f as AuthorizationDetail, g as AuthorizationProbeResult, h as AuthorizationRequest, i as AuthorizationUrlOptions, j as AuthorizeEndpoints, k as CallbackParams, l as ClientCredentialsRequest, m as ConsumerMaintenanceEndpoints, n as ConsumerUserEndpoints, E as ExecuteStepRequest, F as FlowEndpoints, o as FlowInitResponse, p as FlowSessionStatus, q as FlowStep, r as FlowStepCompleteResult, s as FlowStepInProgressResult, t as FlowStepResult, H as HandleCallbackOptions, I as InitAuthenticationRequest, u as InitRegistrationRequest, v as IntrospectTokenRequest, M as MaintenanceStatus, w as MfaDevice, x as MfaEndpoints, O as OAuthAuthorizationServerMetadata, y as OAuthMetaEndpoints, z as OidcDiscoveryDocument, B as OidcEndpoints, P as PageQuery, D as PageResponse, G as PasswordResetEndpoints, J as PasswordTokenRequest, K as PublicClientInfo, L as PushAuthorizationRequestOptions, N as PushedAuthorizationResult, R as RefreshTokenRequest, Q as RevocationResponse, S as RevokeSessionRequest, T as RevokeTokenRequest, U as SessionDetail, V as SessionEndpoints, W as SessionListQuery, X as SessionSummary, Y as TokenEndpoints, Z as TokenExchangeRequest, _ as TokenIntrospectionResponse, $ as TokenStorage, a0 as UpdateSessionRequest, a1 as UserEndpoints, a2 as UserInfoResponse, a3 as UserProfile, a4 as WebAuthnEndpoints, a5 as createMemoryTokenStorage } from './memory-CSq_KMM2.js';
1
+ import { A as AuthClientConfig, C as ConsumerAuthClient, a as AuthClient, b as AuthTokens } from './memory-DCHtjktX.js';
2
+ export { c as AuthorizationCodeTokenRequest, d as AuthorizationConsentBody, e as AuthorizationConsentResponse, f as AuthorizationDetail, g as AuthorizationProbeResult, h as AuthorizationRequest, i as AuthorizationUrlOptions, j as AuthorizeEndpoints, k as CallbackParams, l as ClientCredentialsRequest, m as ConsumerMaintenanceEndpoints, n as ConsumerUserEndpoints, E as EmailVerificationResponse, o as ExecuteStepRequest, F as FlowEndpoints, p as FlowInitResponse, q as FlowSessionStatus, r as FlowStep, s as FlowStepCompleteResult, t as FlowStepInProgressResult, u as FlowStepResult, H as HandleCallbackOptions, I as InitAuthenticationRequest, v as InitRegistrationRequest, w as IntrospectTokenRequest, M as MaintenanceStatus, x as MfaDevice, y as MfaEndpoints, O as OAuthAuthorizationServerMetadata, z as OAuthMetaEndpoints, B as OidcDiscoveryDocument, D as OidcEndpoints, P as PageQuery, G as PageResponse, J as PasswordResetEndpoints, K as PasswordTokenRequest, L as PublicClientInfo, N as PushAuthorizationRequestOptions, Q as PushedAuthorizationResult, R as RefreshTokenRequest, S as RevocationResponse, T as RevokeSessionRequest, U as RevokeTokenRequest, V as SessionDetail, W as SessionEndpoints, X as SessionListQuery, Y as SessionSummary, Z as StartEmailVerificationRequest, _ as TokenEndpoints, $ as TokenExchangeRequest, a0 as TokenIntrospectionResponse, a1 as TokenStorage, a2 as UpdateSessionRequest, a3 as UserEndpoints, a4 as UserInfoResponse, a5 as UserProfile, a6 as VerifyEmailVerificationRequest, a7 as WebAuthnEndpoints, a8 as createMemoryTokenStorage } from './memory-DCHtjktX.js';
3
3
 
4
4
  /**
5
5
  * Creates a consumer-only auth client for public npm distribution.
@@ -107,7 +107,7 @@ declare function validateStorageKey(key: string): string;
107
107
  declare function serializeAuthTokens(tokens: AuthTokens): string;
108
108
 
109
109
  /** Supported normalized auth error codes returned by the SDK. */
110
- type AuthErrorCode = "mfa_required" | "invalid_request" | "invalid_client" | "invalid_grant" | "unauthorized_client" | "unsupported_grant_type" | "invalid_scope" | "access_denied" | "unsupported_response_type" | "server_error" | "temporarily_unavailable" | "invalid_token" | "insufficient_scope" | "authentication_required" | "insufficient_user_authentication" | "http_error" | "network_error" | "timeout" | "unknown_error";
110
+ type AuthErrorCode = "mfa_required" | "invalid_request" | "invalid_client" | "invalid_grant" | "unauthorized_client" | "unsupported_grant_type" | "invalid_scope" | "access_denied" | "unsupported_response_type" | "server_error" | "temporarily_unavailable" | "invalid_token" | "insufficient_scope" | "authentication_required" | "insufficient_user_authentication" | "http_error" | "network_error" | "timeout" | "contract_error" | "unknown_error";
111
111
  /** Base SDK error type for HTTP, OAuth, and transport failures. */
112
112
  declare class AuthError extends Error {
113
113
  readonly code: AuthErrorCode;
@@ -123,6 +123,10 @@ declare class MFARequiredAuthError extends AuthError {
123
123
  readonly mfaMethods: string[];
124
124
  constructor(message: string, mfaMethods: string[], status?: number, details?: unknown);
125
125
  }
126
+ /** The server returned a successful HTTP status with an invalid response body. */
127
+ declare class AuthContractError extends AuthError {
128
+ constructor(message: string, details?: unknown);
129
+ }
126
130
  /** Type guard for SDK errors. */
127
131
  declare function isAuthError(error: unknown): error is AuthError;
128
132
  /** Returns true for errors that should clear local token state. */
@@ -180,4 +184,4 @@ declare function sanitizePostAuthRedirect(value?: string | null, fallback?: stri
180
184
  /** Default OIDC scope set covering identity claims plus refresh capability. */
181
185
  declare const DEFAULT_AUTHORIZE_SCOPE = "openid profile email offline_access";
182
186
 
183
- export { ConsumerAuthClient as AuthClient, AuthClientConfig, AuthError, type AuthErrorCode, AuthTokens, type CodeChallengeMethod, ConsumerAuthClient, DEFAULT_AUTHORIZE_SCOPE, DEFAULT_TOKEN_STORAGE_KEY, MAX_STORED_TOKEN_BYTES, MFARequiredAuthError, type PhoneOtpClient, type PhoneOtpClientConfig, PhoneOtpError, type PhoneOtpFlowMode, type PhoneOtpGuestProfile, type PhoneOtpProfile, type PhoneOtpStart, type PhoneOtpTokens, type PkcePair, assertValidAuthTokens, createAuthClient, createPhoneOtpClient, deriveCodeChallenge, generateCodeVerifier, generateNonce, generatePkce, generateState, isAuthError, isUnrecoverableAuthError, parseStoredAuthTokens, randomUrlSafeString, safeParseStoredJson, sanitizePostAuthRedirect, serializeAuthTokens, timingSafeEqual, validateStorageKey };
187
+ export { ConsumerAuthClient as AuthClient, AuthClientConfig, AuthContractError, AuthError, type AuthErrorCode, AuthTokens, type CodeChallengeMethod, ConsumerAuthClient, DEFAULT_AUTHORIZE_SCOPE, DEFAULT_TOKEN_STORAGE_KEY, MAX_STORED_TOKEN_BYTES, MFARequiredAuthError, type PhoneOtpClient, type PhoneOtpClientConfig, PhoneOtpError, type PhoneOtpFlowMode, type PhoneOtpGuestProfile, type PhoneOtpProfile, type PhoneOtpStart, type PhoneOtpTokens, type PkcePair, assertValidAuthTokens, createAuthClient, createPhoneOtpClient, deriveCodeChallenge, generateCodeVerifier, generateNonce, generatePkce, generateState, isAuthError, isUnrecoverableAuthError, parseStoredAuthTokens, randomUrlSafeString, safeParseStoredJson, sanitizePostAuthRedirect, serializeAuthTokens, timingSafeEqual, validateStorageKey };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var i=class extends Error{code;status;details;constructor(t,n,o){super(n),this.name="AuthError",this.code=t,this.status=o?.status,this.details=o?.details}},T=class extends i{mfaMethods;constructor(t,n,o,r){super("mfa_required",t,{status:o,details:r}),this.name="MFARequiredAuthError",this.mfaMethods=n}};function Ue(e){switch(e){case"mfa_required":case"invalid_request":case"invalid_client":case"invalid_grant":case"unauthorized_client":case"unsupported_grant_type":case"invalid_scope":case"access_denied":case"unsupported_response_type":case"server_error":case"temporarily_unavailable":case"invalid_token":case"insufficient_scope":case"authentication_required":case"insufficient_user_authentication":return e;default:return"unknown_error"}}function ze(e,t){if(!t)return new i("http_error",`Request failed with status ${e}`,{status:e});let n=Ue(t.error),o=t.error_description??t.reason??(t.error?`Auth error: ${t.error}`:`Request failed with status ${e}`);if(n==="mfa_required"){let r=Array.isArray(t.mfa_methods)?t.mfa_methods.filter(s=>typeof s=="string"):[];return new T(o,r,e,t)}return new i(n,o,{status:e,details:t})}async function re(e){let t,n=await e.text();if(n)try{t=JSON.parse(n)}catch{t={reason:n}}return ze(e.status,t)}function U(e){return e instanceof i}function xe(e){return U(e)?e.code==="invalid_client"||e.code==="invalid_grant"||e.code==="unauthorized_client"||e.code==="invalid_token":!1}function J(e){if(!Array.isArray(e))return;let t=e.filter(n=>typeof n=="object"&&n!==null&&typeof n.type=="string");return t.length>0?t:void 0}async function l(e){let t=await e.getTokens();if(!t?.accessToken)throw new i("invalid_token","No access token is available. Authenticate first.");return t.accessToken}function g(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>typeof t<"u"))}function b(e,t){let n=e.access_token,o=e.token_type,r=e.expires_in;if(typeof n!="string"||typeof o!="string"||typeof r!="number")throw new i("unknown_error","Unexpected token response payload.",{details:e});let s={accessToken:n,tokenType:o,expiresIn:r},a=typeof e.refresh_token=="string"?e.refresh_token:t;a&&(s.refreshToken=a),typeof e.scope=="string"&&(s.scope=e.scope),typeof e.id_token=="string"&&(s.idToken=e.id_token);let u=J(e.authorization_details);return u&&(s.authorizationDetails=u),s}function De(e){return{id:String(e.id??""),deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),browser:typeof e.browser=="string"?e.browser:void 0,os:typeof e.os=="string"?e.os:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0}}function H(e){return{id:String(e.id??""),deviceId:typeof e.device_id=="string"?e.device_id:void 0,deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),userAgent:typeof e.user_agent=="string"?e.user_agent:void 0,browser:typeof e.browser=="string"?e.browser:void 0,browserVersion:typeof e.browser_version=="string"?e.browser_version:void 0,os:typeof e.os=="string"?e.os:void 0,osVersion:typeof e.os_version=="string"?e.os_version:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isRevoked:!!e.is_revoked,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,requiresMfa:!!e.requires_mfa,accessTokenCount:typeof e.access_token_count=="number"?e.access_token_count:0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,expiresAt:typeof e.expires_at=="string"?e.expires_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0,revokedAt:typeof e.revoked_at=="string"?e.revoked_at:void 0,revocationReason:typeof e.revocation_reason=="string"?e.revocation_reason:void 0}}function V(e){return{success:!!e.success,sessionsRevoked:typeof e.sessions_revoked=="number"?e.sessions_revoked:0,tokensRevoked:typeof e.tokens_revoked=="number"?e.tokens_revoked:0}}function je(e){let t=Array.isArray(e.items)?e.items:[],o=e.metadata&&typeof e.metadata=="object"?e.metadata:{};return{items:t.filter(r=>typeof r=="object"&&r!==null).map(De),metadata:{page:typeof o.page=="number"?o.page:1,per:typeof o.per=="number"?o.per:t.length,total:typeof o.total=="number"?o.total:t.length}}}function se(e){return{async list(t){let n=await l(e),o=new URLSearchParams;typeof t?.page=="number"&&o.set("page",String(t.page)),typeof t?.perPage=="number"&&o.set("per_page",String(t.perPage)),t?.userId&&o.set("user_id",t.userId);let r=`/api/v1/sessions${o.size?`?${o.toString()}`:""}`,s=await e.http.request(r,{token:n});return je(s)},async current(){let t=await l(e),n=await e.http.request("/api/v1/sessions/current",{token:t});return H(n)},async get(t){let n=await l(e),o=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{token:n});return H(o)},async update(t,n){let o=await l(e),r=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"PATCH",token:o,body:g({device_name:n.deviceName,is_trusted:n.isTrusted})});return H(r)},async revoke(t,n){let o=await l(e),r=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"DELETE",token:o,body:g({reason:n?.reason})});return V(r)},async revokeAll(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all",{method:"POST",token:t});return V(n)},async revokeAllDevices(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all-devices",{method:"POST",token:t});return V(n)}}}function ie(){let e=globalThis.crypto;if(!e?.getRandomValues)throw new i("invalid_request","Web Crypto API is unavailable in this runtime. PKCE requires globalThis.crypto.");return e}function ae(e){let t="";for(let o of e)t+=String.fromCharCode(o);if(typeof btoa!="function")throw new i("server_error","base64UrlEncode requires globalThis.btoa (Web/Deno runtime).");return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function x(e=32){if(!Number.isInteger(e)||e<=0)throw new i("invalid_request","randomUrlSafeString length must be a positive integer.");let t=new Uint8Array(e);return ie().getRandomValues(t),ae(t)}function D(){return x(32)}function j(){return x(32)}function ue(){return x(32)}async function de(e){let t=ie();if(!t.subtle?.digest)throw new i("invalid_request","SubtleCrypto.digest is unavailable; cannot derive an S256 code challenge.");let n=new TextEncoder().encode(e),o=await t.subtle.digest("SHA-256",n);return ae(new Uint8Array(o))}async function M(e="S256"){let t=ue();if(e==="plain")return{codeVerifier:t,codeChallenge:t,codeChallengeMethod:"plain"};let n=await de(t);return{codeVerifier:t,codeChallenge:n,codeChallengeMethod:"S256"}}function Q(e,t){let n=new TextEncoder().encode(e),o=new TextEncoder().encode(t),r=Math.max(n.length,o.length),s=n.length^o.length;for(let a=0;a<r;a+=1)s|=(n[a]??0)^(o[a]??0);return s===0}function Me(e){return{active:!!e.active,scope:typeof e.scope=="string"?e.scope:void 0,clientId:typeof e.client_id=="string"?e.client_id:void 0,username:typeof e.username=="string"?e.username:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,exp:typeof e.exp=="number"?e.exp:void 0,iat:typeof e.iat=="number"?e.iat:void 0,sub:typeof e.sub=="string"?e.sub:void 0,authorizationDetails:J(e.authorization_details)}}function $(e){return{async password(t){let n=g({grant_type:"password",client_id:e.config.clientId,client_secret:e.config.clientSecret,username:t.username,email:t.email,password:t.password,scope:t.scope,mfa_code:t.mfaCode,mfa_backup_code:t.mfaBackupCode}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r},async refresh(t){let n=await e.getTokens(),o=t?.refreshToken??n?.refreshToken;if(!o)throw new i("invalid_request","No refresh token is available.");let r=g({grant_type:"refresh_token",client_id:e.config.clientId,client_secret:e.config.clientSecret,refresh_token:o,scope:t?.scope}),s=await e.http.request("/oauth/token",{method:"POST",body:r}),a=b(s,o);return await e.setTokens(a),a},async clientCredentials(t){let n=g({grant_type:"client_credentials",client_id:e.config.clientId,client_secret:e.config.clientSecret,scope:t?.scope}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r},async authorizationCode(t){let n=g({grant_type:"authorization_code",client_id:e.config.clientId,client_secret:e.config.clientSecret,code:t.code,redirect_uri:t.redirectUri,code_verifier:t.codeVerifier,scope:t.scope}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r},async revoke(t){let n=await e.getTokens(),o=t?.token??n?.accessToken;if(!o)throw new i("invalid_request","No token provided for revocation.");await e.http.request("/oauth/revoke",{method:"POST",body:g({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:o,token_type_hint:t?.tokenTypeHint})}),n&&(o===n.accessToken||o===n.refreshToken)&&await e.clearTokens()},async introspect(t){let n=await e.http.request("/oauth/introspect",{method:"POST",body:g({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:t.token})});return Me(n)},async tokenExchange(t){let n=g({grant_type:"urn:ietf:params:oauth:grant-type:token-exchange",client_id:e.config.clientId,client_secret:e.config.clientSecret,subject_token:t.subjectToken,subject_token_type:t.subjectTokenType??"urn:ietf:params:oauth:token-type:access_token",requested_subject:t.requestedSubject,scope:t.scope,audience:t.audience}),o=await e.http.request("/oauth/token",{method:"POST",body:n}),r=b(o);return await e.setTokens(r),r}}}function ce(e,t){let n=e.trim();if(!n)throw new i("invalid_request",`${t} is required.`);return n}async function _(e,t,n){let o=await l(e),r=n?.query,s=r&&Object.keys(r).length>0?`?${new URLSearchParams(Object.entries(r).filter(([,a])=>typeof a<"u").map(([a,u])=>[a,String(u)])).toString()}`:"";return e.http.request(`${t}${s}`,{method:n?.method,body:n?.body,token:o})}async function S(e,t,n){await _(e,t,n)}function A(e,t){return encodeURIComponent(ce(e,t))}function $e(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(n=>typeof n=="string"):void 0;return{redirectUri:String(e.redirect_uri??""),code:typeof e.code=="string"?e.code:void 0,state:typeof e.state=="string"?e.state:void 0,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,mfaMethods:t,accessToken:typeof e.access_token=="string"?e.access_token:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,expiresIn:typeof e.expires_in=="number"?e.expires_in:void 0,scope:typeof e.scope=="string"?e.scope:void 0,idToken:typeof e.id_token=="string"?e.id_token:void 0}}function Ne(e){let t=Array.isArray(e.redirect_uris)?e.redirect_uris.filter(n=>typeof n=="string"&&n.length>0):[];return{clientId:String(e.client_id??""),name:String(e.name??""),description:typeof e.description=="string"?e.description:void 0,isFirstParty:!!e.is_first_party,redirectUris:t}}function Fe(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(o=>typeof o=="string"):void 0,n=Array.isArray(e.uncovered_scopes)?e.uncovered_scopes.filter(o=>typeof o=="string"):void 0;return{consentSatisfied:!!e.consent_satisfied,requiresMfa:!!e.requires_mfa,mfaMethods:t,uncoveredScopes:n,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,code:typeof e.code=="string"?e.code:void 0,redirectUri:typeof e.redirect_uri=="string"?e.redirect_uri:void 0,state:typeof e.state=="string"?e.state:void 0}}function pe(e){if(!e.password&&!e.accessToken)throw new i("invalid_request","Either password or accessToken is required for consent.")}function fe(e,t){let n=new URL(e),o=new URL(t);if(n.origin!==o.origin||n.pathname!=="/oauth/authorize/consent")throw new i("invalid_request","callbackUrl must target /oauth/authorize/consent on the configured auth server.");return n}function le(e){async function t(o,r){pe(r);let s=fe(o,e.config.baseUrl),a={username:r.username,approved:r.approved??!0,requested_scopes:r.requestedScopes,mfa_code:r.mfaCode,mfa_backup_code:r.mfaBackupCode};r.password!==void 0&&(a.password=r.password);let u=await e.http.request(`${s.pathname}${s.search}`,{method:"POST",token:r.accessToken,body:a}),f=$e(u);if(f.error==="mfa_required")throw new T(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}async function n(o,r){pe(r);let s=fe(o,e.config.baseUrl),a={username:r.username,requested_scopes:r.requestedScopes,mfa_code:r.mfaCode,mfa_backup_code:r.mfaBackupCode};r.password!==void 0&&(a.password=r.password);let u=await e.http.request(`${s.pathname}/evaluate${s.search}`,{method:"POST",token:r.accessToken,body:a}),f=Fe(u);if(f.error==="mfa_required"||f.requiresMfa)throw new T(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}return{consent:t,evaluateConsent:n,consentWithCredentials(o){return t(o.callbackUrl,{username:o.username,password:o.password,accessToken:o.accessToken,approved:o.approved,requestedScopes:o.requestedScopes,mfaCode:o.mfaCode,mfaBackupCode:o.mfaBackupCode})},evaluateConsentWithCredentials(o){return n(o.callbackUrl,{username:o.username,password:o.password,accessToken:o.accessToken,requestedScopes:o.requestedScopes,mfaCode:o.mfaCode,mfaBackupCode:o.mfaBackupCode})}}}function me(e){return{async publicClient(t){let n=await e.http.request(`/oauth/clients/${encodeURIComponent(t)}/public`);return Ne(n)},async discoverAuthorizationServer(){let t=await e.http.request("/.well-known/oauth-authorization-server");return{issuer:String(t.issuer??""),authorizationEndpoint:String(t.authorization_endpoint??""),tokenEndpoint:String(t.token_endpoint??""),jwksUri:typeof t.jwks_uri=="string"?t.jwks_uri:void 0,revocationEndpoint:typeof t.revocation_endpoint=="string"?t.revocation_endpoint:void 0,introspectionEndpoint:typeof t.introspection_endpoint=="string"?t.introspection_endpoint:void 0,registrationEndpoint:typeof t.registration_endpoint=="string"?t.registration_endpoint:void 0,scopesSupported:Array.isArray(t.scopes_supported)?t.scopes_supported.filter(n=>typeof n=="string"):void 0,responseTypesSupported:Array.isArray(t.response_types_supported)?t.response_types_supported.filter(n=>typeof n=="string"):[],grantTypesSupported:Array.isArray(t.grant_types_supported)?t.grant_types_supported.filter(n=>typeof n=="string"):void 0,codeChallengeMethodsSupported:Array.isArray(t.code_challenge_methods_supported)?t.code_challenge_methods_supported.filter(n=>typeof n=="string"):void 0,pushedAuthorizationRequestEndpoint:typeof t.pushed_authorization_request_endpoint=="string"?t.pushed_authorization_request_endpoint:void 0,requirePushedAuthorizationRequests:typeof t.require_pushed_authorization_requests=="boolean"?t.require_pushed_authorization_requests:void 0,authorizationDetailsTypesSupported:Array.isArray(t.authorization_details_types_supported)?t.authorization_details_types_supported.filter(n=>typeof n=="string"):void 0,raw:t}}}}var W="openid profile email offline_access",he=new Set(["response_type","client_id","redirect_uri","scope","state","nonce","code_challenge","code_challenge_method","prompt","login_hint","authorization_details","request_uri"]);function Le(e){if(typeof e=="string"){let t=e.indexOf("?"),n=t>=0?e.slice(t+1):e;return new URLSearchParams(n)}return e instanceof URLSearchParams?e:"raw"in e&&typeof e.raw=="object"?new URLSearchParams(e.raw):new URLSearchParams(e)}function ge(e){let t=Le(e),n={};return t.forEach((o,r)=>{n[r]=o}),{code:t.get("code")??void 0,state:t.get("state")??void 0,error:t.get("error")??void 0,errorDescription:t.get("error_description")??void 0,errorUri:t.get("error_uri")??void 0,raw:n}}function ye(e){let t=$(e);return{...le(e),async createRequest(o){if(!o.redirectUri?.trim())throw new i("invalid_request","redirectUri is required to build an authorization request.");let r=o.scope??W,s=o.state??D(),a=o.nonce??j(),u=await M(o.codeChallengeMethod??"S256"),f=o.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,R=new URL(f),m=R.searchParams;m.set("response_type",o.responseType??"code"),m.set("client_id",e.config.clientId),m.set("redirect_uri",o.redirectUri),m.set("scope",r),m.set("state",s),m.set("nonce",a),m.set("code_challenge",u.codeChallenge),m.set("code_challenge_method",u.codeChallengeMethod),o.authorizationDetails&&o.authorizationDetails.length>0&&m.set("authorization_details",JSON.stringify(o.authorizationDetails)),o.prompt&&m.set("prompt",o.prompt),o.loginHint&&m.set("login_hint",o.loginHint);for(let[w,O]of Object.entries(o.extraParams??{})){if(he.has(w))throw new i("invalid_request",`extraParams may not override the reserved authorization parameter "${w}".`);m.set(w,O)}return{url:R.toString(),state:s,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:o.redirectUri,scope:r}},async pushAuthorizationRequest(o){if(!o.redirectUri?.trim())throw new i("invalid_request","redirectUri is required to push an authorization request.");let r=o.scope??W,s=o.state??D(),a=o.nonce??j(),u=await M(o.codeChallengeMethod??"S256"),f={response_type:o.responseType??"code",client_id:e.config.clientId,redirect_uri:o.redirectUri,scope:r,state:s,nonce:a,code_challenge:u.codeChallenge,code_challenge_method:u.codeChallengeMethod};e.config.clientSecret&&(f.client_secret=e.config.clientSecret),o.authorizationDetails&&o.authorizationDetails.length>0&&(f.authorization_details=JSON.stringify(o.authorizationDetails));for(let[h,c]of Object.entries(o.extraParams??{})){if(he.has(h))throw new i("invalid_request",`extraParams may not override the reserved authorization parameter "${h}".`);f[h]=c}let R=await e.http.request("/oauth/par",{method:"POST",body:f}),m=R.request_uri,w=R.expires_in;if(typeof m!="string"||typeof w!="number")throw new i("unknown_error","Unexpected pushed authorization response payload.",{details:R});let O=o.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,p=new URL(O);return p.searchParams.set("client_id",e.config.clientId),p.searchParams.set("request_uri",m),{requestUri:m,expiresIn:w,request:{url:p.toString(),state:s,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:o.redirectUri,scope:r,requestUri:m}}},parseCallback:ge,async probeAuthorize(o){let r=await e.http.requestRaw(o,{headers:{Accept:"application/json"},redirect:"manual"}),s=r.headers.get("location");if(s&&r.status>=300&&r.status<400)return{kind:"redirect",location:s,status:r.status};let a=await r.text(),u=a?JSON.parse(a):{};if(!r.ok)throw new i("server_error",typeof u.error_description=="string"?u.error_description:"Authorization probe failed",{status:r.status,details:u});let f=typeof u.authorization_url=="string"?u.authorization_url:void 0;return{kind:"json",status:r.status,authorizationUrl:f,payload:u}},async handleCallback(o){let s=typeof o.callback=="object"&&!(o.callback instanceof URLSearchParams)&&"raw"in o.callback?o.callback:ge(o.callback);if(s.error)throw new i("access_denied",s.errorDescription??`Authorization failed: ${s.error}`,{details:s.raw});if(!s.state||!Q(s.state,o.expectedState))throw new i("invalid_request","State mismatch on authorization callback (possible CSRF).");if(!s.code)throw new i("invalid_request","Authorization callback is missing the `code` parameter.");return t.authorizationCode({code:s.code,redirectUri:o.redirectUri,codeVerifier:o.codeVerifier,scope:o.scope})}}}function P(e){let t=e.step_id,n=e.step_type,o=e.name,r=e.order,s=e.is_required,a=e.timeout;if(typeof t!="string"||typeof n!="string"||typeof o!="string"||typeof r!="number"||typeof s!="boolean"||typeof a!="number")throw new i("unknown_error","Unexpected flow step payload.",{details:e});return{stepId:t,stepType:n,name:o,description:typeof e.description=="string"?e.description:void 0,order:r,isRequired:s,timeout:a,inputSchema:e.input_schema&&typeof e.input_schema=="object"?e.input_schema:void 0}}function G(e){let t=e.current_step,n=e.remaining_steps;if(!t||typeof t!="object")throw new i("unknown_error","Missing current_step in flow response.",{details:e});let o=e.continuation_token;if(typeof o!="string"||!o)throw new i("unknown_error","Missing continuation_token in flow response.",{details:e});return{sessionId:String(e.session_id??""),flowId:String(e.flow_id??""),flowName:String(e.flow_name??""),currentStep:P(t),remainingSteps:Array.isArray(n)?n.filter(r=>typeof r=="object"&&r!==null).map(P):[],expiresAt:String(e.expires_at??""),continuationToken:o}}function Be(e){return{sessionId:String(e.session_id??""),status:String(e.status??""),purpose:String(e.purpose??""),currentStep:e.current_step&&typeof e.current_step=="object"?P(e.current_step):void 0,completedSteps:Array.isArray(e.completed_steps)?e.completed_steps.filter(t=>typeof t=="string"):[],remainingSteps:Array.isArray(e.remaining_steps)?e.remaining_steps.filter(t=>typeof t=="object"&&t!==null).map(P):[],failedAttempts:typeof e.failed_attempts=="number"?e.failed_attempts:0,expiresAt:String(e.expires_at??""),lastActivityAt:String(e.last_activity_at??"")}}async function K(e,t){let n=t.status;if(n==="error"||typeof t.error=="string"&&n!=="in_progress"&&n!=="complete")throw new i("invalid_request",typeof t.error=="string"?t.error:"Flow step failed.",{details:t});if(n==="in_progress"){let o=t.next_step,r=t.remaining_steps;if(!o||typeof o!="object")throw new i("unknown_error","Missing next_step in flow step response.",{details:t});let s=t.debug&&typeof t.debug=="object"&&!Array.isArray(t.debug)?t.debug:void 0;return{status:"in_progress",sessionId:String(t.session_id??""),nextStep:P(o),completedSteps:Array.isArray(t.completed_steps)?t.completed_steps.filter(u=>typeof u=="string"):[],remainingSteps:Array.isArray(r)?r.filter(u=>typeof u=="object"&&u!==null).map(P):[],debug:s}}if(n==="complete"){let o=b(t);return await e.setTokens(o),{status:"complete",accessToken:o.accessToken,refreshToken:o.refreshToken,tokenType:o.tokenType,expiresIn:o.expiresIn,scope:o.scope,amr:Array.isArray(t.amr)?t.amr.filter(s=>typeof s=="string"):[],acr:typeof t.acr=="string"?t.acr:""}}throw new i("unknown_error","Unknown flow step status.",{details:t})}function _e(e){return{async initAuthentication(t){let n=await e.http.request("/oauth/authenticate/init",{method:"POST",body:g({client_id:t?.clientId??e.config.clientId,username:t?.username,flow_type:t?.flowType})});return G(n)},async executeStep(t){let n=await e.http.request("/oauth/authenticate/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return K(e,n)},async initRegistration(t){let n=await e.http.request("/oauth/register/init",{method:"POST",body:g({client_id:t?.clientId??e.config.clientId,invite_code:t?.inviteCode,flow_type:t?.flowType})});return G(n)},async executeRegistrationStep(t){let n=await e.http.request("/oauth/register/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return K(e,n)},async getStatus(t,n){let o=new URLSearchParams({continuation_token:n}),r=await e.http.request(`/oauth/flow/status/${encodeURIComponent(t)}?${o}`);return Be(r)},async initRecovery(t){let n=await e.http.request("/oauth/recovery/init",{method:"POST",body:g({client_id:t?.clientId??e.config.clientId,recovery_type:t?.recoveryType,redirect_uri:t?.redirectUri})});return G(n)},async executeRecoveryStep(t){let n=await e.http.request("/oauth/recovery/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return K(e,n)}}}function N(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function Je(e){return{issuer:String(e.issuer??""),authorizationEndpoint:String(e.authorization_endpoint??""),tokenEndpoint:String(e.token_endpoint??""),userinfoEndpoint:typeof e.userinfo_endpoint=="string"?e.userinfo_endpoint:void 0,jwksUri:String(e.jwks_uri??""),revocationEndpoint:typeof e.revocation_endpoint=="string"?e.revocation_endpoint:void 0,introspectionEndpoint:typeof e.introspection_endpoint=="string"?e.introspection_endpoint:void 0,responseTypesSupported:N(e.response_types_supported),grantTypesSupported:N(e.grant_types_supported),scopesSupported:N(e.scopes_supported),codeChallengeMethodsSupported:N(e.code_challenge_methods_supported),raw:e}}function He(e){return{sub:String(e.sub??""),name:typeof e.name=="string"?e.name:void 0,givenName:typeof e.given_name=="string"?e.given_name:void 0,familyName:typeof e.family_name=="string"?e.family_name:void 0,middleName:typeof e.middle_name=="string"?e.middle_name:void 0,nickname:typeof e.nickname=="string"?e.nickname:void 0,preferredUsername:typeof e.preferred_username=="string"?e.preferred_username:void 0,profile:typeof e.profile=="string"?e.profile:void 0,picture:typeof e.picture=="string"?e.picture:void 0,website:typeof e.website=="string"?e.website:void 0,gender:typeof e.gender=="string"?e.gender:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0,zoneinfo:typeof e.zoneinfo=="string"?e.zoneinfo:void 0,locale:typeof e.locale=="string"?e.locale:void 0,updatedAt:typeof e.updated_at=="number"?e.updated_at:void 0,email:typeof e.email=="string"?e.email:void 0,emailVerified:typeof e.email_verified=="boolean"?e.email_verified:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,phoneNumberVerified:typeof e.phone_number_verified=="boolean"?e.phone_number_verified:void 0}}function ke(e){return{async userInfo(){let t=await l(e),n=await e.http.request("/oauth/userinfo",{token:t});return He(n)},async discover(){let t=await e.http.request("/.well-known/openid-configuration");return Je(t)},async jwks(){let t=await e.http.request("/oauth/jwks");return{keys:Array.isArray(t.keys)?t.keys.filter(o=>typeof o=="object"&&o!==null):[]}}}}function F(e){return{...e,id:typeof e.id=="string"?e.id:"",organizationId:typeof e.organization_id=="string"?e.organization_id:void 0,email:typeof e.email=="string"?e.email:void 0,username:typeof e.username=="string"?e.username:void 0,firstName:typeof e.first_name=="string"?e.first_name:void 0,lastName:typeof e.last_name=="string"?e.last_name:void 0,isActive:typeof e.is_active=="boolean"?e.is_active:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0,mfaEnabled:typeof e.mfa_enabled=="boolean"?e.mfa_enabled:void 0}}function Y(e){return{id:String(e.id??""),name:typeof e.name=="string"?e.name:void 0,email:typeof e.email=="string"?e.email:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,relationship:typeof e.relationship=="string"?e.relationship:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0}}function Ve(e){return{id:String(e.id??""),provider:String(e.provider??""),providerUserId:typeof e.provider_user_id=="string"?e.provider_user_id:void 0,email:typeof e.email=="string"?e.email:void 0,isPrimary:typeof e.is_primary=="boolean"?e.is_primary:void 0}}function be(e){return Qe(e)}function Qe(e){return{async me(){let t=await l(e),n=await e.http.request("/api/v1/users/me",{token:t});return F(n)},async updateMe(t){let n=await _(e,"/api/v1/users/me",{method:"PATCH",body:t});return F(n)},async changePassword(t){await S(e,"/api/v1/users/me/password",{method:"POST",body:{current_password:t.currentPassword,new_password:t.newPassword}})},async deleteAvatar(){let t=await _(e,"/api/v1/users/me/avatar",{method:"DELETE"});return F(t)},async uploadAvatar(t,n="avatar.jpg"){let o=await l(e),r=new FormData,s=t instanceof Blob?t:new Blob([new Uint8Array(t)]);r.append("avatar",s,n);let a=await e.http.request("/api/v1/users/me/avatar",{method:"POST",token:o,body:r});return F(a)},async verifyPhone(t){return _(e,"/api/v1/users/me/phone/verify",{method:"POST",body:t})},async verifyRecoveryEmail(t){return _(e,"/api/v1/users/me/recovery-email/verify",{method:"POST",body:t})},async securityOverview(){return _(e,"/api/v1/users/me/security-overview")},recoveryContacts:{async list(){let t=await _(e,"/api/v1/users/me/recovery-contacts");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(Y):[]},async create(t){let n=await _(e,"/api/v1/users/me/recovery-contacts",{method:"POST",body:t});return Y(n)},async update(t,n){let o=await _(e,`/api/v1/users/me/recovery-contacts/${A(t,"contactId")}`,{method:"PATCH",body:n});return Y(o)},async delete(t){await S(e,`/api/v1/users/me/recovery-contacts/${A(t,"contactId")}`,{method:"DELETE"})}},identities:{async list(){let t=await _(e,"/api/v1/users/me/identities");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(Ve):[]},async unlink(t){await S(e,`/api/v1/users/me/identities/${A(t,"identityId")}`,{method:"DELETE"})},async setPrimary(t){return _(e,`/api/v1/users/me/identities/${A(t,"identityId")}/primary`,{method:"PATCH"})}},async deleteMe(t){await S(e,"/api/v1/users/me",{method:"DELETE",body:{password:t.password}})}}}function C(e){return e&&typeof e=="object"?e:{}}function Re(e){return{async registerBegin(t){let n=await l(e),o=await e.http.request("/api/v1/users/me/webauthn/register/begin",{method:"POST",token:n,body:t});return C(o)},async registerFinish(t){let n=await l(e),o=await e.http.request("/api/v1/users/me/webauthn/register/finish",{method:"POST",token:n,body:t});return C(o)},async authenticateBegin(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/begin",{method:"POST",body:t});return C(n)},async authenticateFinish(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/finish",{method:"POST",body:t}),o=C(n);if(typeof o.access_token=="string"){let r=b(o);await e.setTokens(r)}return o},async credentials(){let t=await l(e),n=await e.http.request("/api/v1/users/me/webauthn/credentials",{token:t});return C(n)},async removeCredential(t,n){let o=await l(e);await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}`,{method:"DELETE",token:o,body:n?.password?{password:n.password}:void 0})},async renameCredential(t,n){let o=await l(e),r=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/rename`,{method:"PATCH",token:o,body:n});return C(r)},async setPrimaryCredential(t){let n=await l(e),o=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/primary`,{method:"POST",token:n});return C(o)}}}function We(e){return{isActive:!!(e.is_active??e.isActive),message:typeof e.message=="string"?e.message:void 0,scheduledStart:typeof e.scheduled_start=="string"?e.scheduled_start:void 0,scheduledEnd:typeof e.scheduled_end=="string"?e.scheduled_end:void 0,...e}}function we(e){return{async status(){let t=await e.http.request("/api/v1/maintenance/status");return We(t)}}}var Ge=128,X=254;function v(e,t){if(typeof e!="string")return;let n=e.trim();if(!(!n||n.length>t))return n}function Se(e){return{async request(t){let n=g({email:v(t.email,X),identifier:v(t.identifier,X),recovery_email:v(t.recoveryEmail,X),phone_number:v(t.phoneNumber,32),member_id:v(t.memberId,64),security_question:v(t.securityQuestion,256),security_answer:v(t.securityAnswer,256),redirect_uri:v(t.redirectUri,2048)}),o=await e.http.request("/oauth/password/reset/request",{method:"POST",body:n});return{ok:!!o.ok,message:String(o.message??"")}},async validate(t){let n=t.trim();if(!n)throw new i("invalid_request","token is required.");let o=await e.http.request(`/oauth/password/reset/validate?token=${encodeURIComponent(n)}`);return{ok:!!o.ok,valid:!!o.valid,expiresAt:typeof o.expires_at=="string"?o.expires_at:void 0}},async complete(t){if(!t.token.trim())throw new i("invalid_request","token is required.");if(!t.password||t.password.length>Ge)throw new i("invalid_request","password is required and must be <= 128 characters.");let n=await e.http.request("/oauth/password/reset/complete",{method:"POST",body:{token:t.token.trim(),password:t.password,password_confirm:t.passwordConfirm}});return{ok:!!n.ok,message:String(n.message??"")}}}}function Ke(e){return{id:String(e.id??""),deviceName:String(e.device_name??""),isVerified:!!e.is_verified,isPrimary:!!e.is_primary,createdAt:typeof e.created_at=="string"?e.created_at:void 0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0}}function ve(e){return{async setup(t){let n=t.deviceName?.trim();if(!n||n.length>128)throw new i("invalid_request","deviceName is required.");let o=await _(e,"/api/v1/users/me/mfa/setup",{method:"POST",body:{device_name:n}});return{deviceId:String(o.device_id??""),secret:String(o.secret??""),qrCodeUri:String(o.qr_code_uri??""),backupCodes:Array.isArray(o.backup_codes)?o.backup_codes.filter(r=>typeof r=="string"):[],algorithm:String(o.algorithm??""),digits:typeof o.digits=="number"?o.digits:6,period:typeof o.period=="number"?o.period:30}},async verify(t){return _(e,"/api/v1/users/me/mfa/verify",{method:"POST",body:{device_id:t.deviceId,totp_code:t.totpCode}})},async devices(){let t=await _(e,"/api/v1/users/me/mfa/devices");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(Ke):[]},async removeDevice(t){await S(e,`/api/v1/users/me/mfa/devices/${A(t,"deviceId")}`,{method:"DELETE"})},async regenerateBackupCodes(){let t=await _(e,"/api/v1/users/me/mfa/backup-codes/regenerate",{method:"POST"});return{backupCodes:Array.isArray(t.backup_codes)?t.backup_codes.filter(n=>typeof n=="string"):[]}},async disable(t){await S(e,"/api/v1/users/me/mfa/disable",{method:"POST",body:g({password:t?.password})})}}}var Te="https://prod-auth.tktchurch.com",Ye=new Set(["localhost","127.0.0.1","[::1]"]);function Xe(e){return Ye.has(e.toLowerCase())}function Z(e,t={}){let n=(e??Te).trim();if(!n)return Z(Te,t);let r=(/^https?:\/\//i.test(n)?n:`https://${n}`).replace(/\/+$/,""),s;try{s=new URL(r)}catch{throw new i("invalid_request","baseUrl must be a valid absolute URL.")}if(s.protocol==="http:"&&!t.allowInsecureTransport&&!Xe(s.hostname))throw new i("invalid_request","baseUrl must use HTTPS. Set allowInsecureTransport=true only for trusted local development.");return r}function Ze(e,t){if(!e&&t<=0)return{cleanup:()=>{}};let n=new AbortController,o,r=()=>{n.abort(e?.reason)};return e&&(e.aborted?n.abort(e.reason):e.addEventListener("abort",r,{once:!0})),t>0&&(o=setTimeout(()=>{n.abort(new Error(`Request timed out after ${t}ms`))},t)),{signal:n.signal,cleanup:()=>{o&&clearTimeout(o),e&&e.removeEventListener("abort",r)}}}function et(e,t){return/^https?:\/\//i.test(t)?t:`${e}${t.startsWith("/")?t:`/${t}`}`}function tt(e,t,n){let o=new Headers(e);return t&&new Headers(t).forEach((s,a)=>{o.set(a,s)}),n&&!o.has("Authorization")&&o.set("Authorization",`Bearer ${n}`),o}function Ae(e){return{async request(t,n){let o=await this.requestRaw(t,n);if(!o.ok)throw await re(o);if(o.status===204)return;let r=await o.text();if(r)return JSON.parse(r)},async requestRaw(t,n){let o=et(e.baseUrl,t),r=tt(e.defaultHeaders,n?.headers,n?.token),{signal:s,cleanup:a}=Ze(n?.signal,e.timeoutMs),u={method:n?.method??"GET",headers:r,signal:s,redirect:n?.redirect};typeof n?.body<"u"&&(n.body instanceof FormData?u.body=n.body:(r.has("Content-Type")||r.set("Content-Type","application/json"),u.body=JSON.stringify(n.body)));try{return await e.fetch(o,u)}catch(f){throw s?.aborted??!1?new i("timeout",`Request timed out: ${o}`,{details:f}):new i("network_error",`Network request failed: ${o}`,{details:f})}finally{a()}}}}var nt="@tktchurch/auth/tokens",te=32768,Pe=new Set(["accessToken","tokenType","expiresIn","refreshToken","scope","idToken","authorizationDetails"]),Ee=new Set(["__proto__","constructor","prototype"]),ot=/^[\w@./:-]{1,128}$/;function ne(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Ce(e){return typeof e=="string"&&e.length>0}function ee(e){return typeof e=="string"&&e.length>0?e:void 0}function z(e){if(!ne(e))throw new i("invalid_request","Token storage rejected a non-object token payload.");for(let s of Object.keys(e))if(!Pe.has(s))throw new i("invalid_request",`Token storage rejected unknown field "${s}".`);if(!Ce(e.accessToken))throw new i("invalid_request","Token storage requires a non-empty accessToken.");if(!Ce(e.tokenType))throw new i("invalid_request","Token storage requires a non-empty tokenType.");if(typeof e.expiresIn!="number"||!Number.isFinite(e.expiresIn)||e.expiresIn<0)throw new i("invalid_request","Token storage requires a non-negative numeric expiresIn.");let t={accessToken:e.accessToken,tokenType:e.tokenType,expiresIn:e.expiresIn},n=ee(e.refreshToken);n&&(t.refreshToken=n);let o=ee(e.scope);o&&(t.scope=o);let r=ee(e.idToken);if(r&&(t.idToken=r),typeof e.authorizationDetails<"u"){if(!Array.isArray(e.authorizationDetails)||!e.authorizationDetails.every(s=>ne(s)&&typeof s.type=="string"))throw new i("invalid_request","Token storage rejected malformed authorizationDetails.");t.authorizationDetails=e.authorizationDetails}return t}function rt(e){if(!ne(e))return null;for(let t of Object.keys(e))if(Ee.has(t)||!Pe.has(t))return null;try{return z(e)}catch{return null}}function st(e){return JSON.parse(e,(t,n)=>{if(Ee.has(t))throw new SyntaxError("Forbidden JSON key in stored token payload.");return n})}function it(e){let t=e.trim();if(!t)throw new i("invalid_request","Token storage key must be a non-empty string.");if(!ot.test(t))throw new i("invalid_request","Token storage key contains unsupported characters or exceeds 128 characters.");return t}function at(e){let t=z(e),n=JSON.stringify(t);if(n.length>te)throw new i("invalid_request",`Serialized token payload exceeds ${te} bytes.`);return n}var oe=class{state=null;get(){return this.state}set(t){if(!t){this.clear();return}this.state=z(t)}clear(){this.state=null}};function E(){return new oe}function ut(){return typeof window<"u"&&typeof window.document<"u"}function dt(e){if(e)return e;if(typeof globalThis.fetch=="function")return globalThis.fetch.bind(globalThis);throw new i("invalid_request","No fetch implementation available. Provide config.fetch.")}function qe(e){if(!e.clientId?.trim())throw new i("invalid_request","clientId is required.");if(ut()&&e.clientSecret&&!e.allowClientSecretInBrowser)throw new i("invalid_request","clientSecret in browser runtime is blocked by default. Set allowClientSecretInBrowser=true to override.");return{clientId:e.clientId,clientSecret:e.clientSecret,baseUrl:Z(e.baseUrl,{allowInsecureTransport:e.allowInsecureTransport??!1}),fetch:dt(e.fetch),storage:e.storage??E(),timeoutMs:e.timeoutMs??15e3,defaultHeaders:e.defaultHeaders??{},autoRefresh:e.autoRefresh??!0,allowClientSecretInBrowser:e.allowClientSecretInBrowser??!1,allowInsecureTransport:e.allowInsecureTransport??!1}}function L(e){let t=qe(e),n=Ae({baseUrl:t.baseUrl,fetch:t.fetch,timeoutMs:t.timeoutMs,defaultHeaders:t.defaultHeaders}),o=async()=>await t.storage.get(),r=async u=>{await t.storage.set(u)},s=async()=>{await t.storage.clear()},a={config:t,http:n,getTokens:o,setTokens:r,clearTokens:s};return{token:$(a),flow:_e(a),oidc:ke(a),authorize:ye(a),user:be(a),sessions:se(a),webauthn:Re(a),passwordReset:Se(a),mfa:ve(a),maintenance:we(a),oauth:me(a),tokens:{get:o,set:r,clear:s}}}var k=class extends Error{name="PhoneOtpError"};function q(e,t){return e instanceof k?e:U(e)?new k(e.message||t):e instanceof Error&&e.message?new k(e.message):new k(t)}function Oe(e){if(!U(e)||typeof e.status!="number")return!1;let t=e.status;return t>=400&&t<500&&t!==429}function Ie(e){if(e.status!=="in_progress"||!e.debug)return;let t=e.debug.verification_code;return typeof t=="string"?t:void 0}function ct(e){return{...e,id:typeof e.id=="string"?e.id:"",first_name:typeof e.first_name=="string"?e.first_name:typeof e.firstName=="string"?e.firstName:void 0,last_name:typeof e.last_name=="string"?e.last_name:typeof e.lastName=="string"?e.lastName:void 0,email:typeof e.email=="string"?e.email:void 0,phone_number:typeof e.phone_number=="string"?e.phone_number:typeof e.phoneNumber=="string"?e.phoneNumber:void 0,phone_country_code:typeof e.phone_country_code=="string"?e.phone_country_code:typeof e.phoneCountryCode=="string"?e.phoneCountryCode:void 0,phone_verified:typeof e.phone_verified=="boolean"?e.phone_verified:typeof e.phoneVerified=="boolean"?e.phoneVerified:void 0,profile_picture_url:typeof e.profile_picture_url=="string"?e.profile_picture_url:typeof e.profilePictureUrl=="string"?e.profilePictureUrl:void 0,picture:typeof e.picture=="string"?e.picture:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0}}function pt(e){let t=e.auth,n=e.guestProfile??{firstName:"Guest",lastName:"User"},o=n.emailDomain??"registrations.tktchurch.local",r=n.emailLocalPrefix??"reg";function s(){return t||L({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:E(),autoRefresh:!1})}async function a(p,h){let c=s(),d=await c.flow.initAuthentication({flowType:"phone_only",username:h}),y=await c.flow.executeStep({sessionId:d.sessionId,stepId:d.currentStep.stepId,continuationToken:d.continuationToken,credential:p});if(y.status!=="in_progress")throw new k("Unexpected sign-in response.");return{oauthSessionId:d.sessionId,verifyStepId:y.nextStep.stepId,mode:"authentication",continuationToken:d.continuationToken,debugCode:Ie(y)}}async function u(p){let h=s(),c=await h.flow.initRegistration({flowType:"phone_registration"}),d=await h.flow.executeRegistrationStep({sessionId:c.sessionId,stepId:c.currentStep.stepId,continuationToken:c.continuationToken,credential:p});if(d.status!=="in_progress")throw new k("Unexpected verification response.");return{oauthSessionId:c.sessionId,verifyStepId:d.nextStep.stepId,mode:"registration",continuationToken:c.continuationToken,debugCode:Ie(d)}}async function f(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await u(d)}catch(y){if(!Oe(y))throw q(y,"Could not send the code. Please try again.");try{return await a(d,c)}catch{throw q(y,"Could not send the code. Please try again.")}}}async function R(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await a(d,c)}catch(y){if(!Oe(y))throw q(y,"Could not start sign-in.");try{return await u(d)}catch{throw q(y,"Could not start sign-in.")}}}async function m(p,h,c,d,y,I){return h==="registration"?await p.flow.executeRegistrationStep({sessionId:c,stepId:d,continuationToken:y,credential:I}):await p.flow.executeStep({sessionId:c,stepId:d,continuationToken:y,credential:I})}async function w(p,h){let c=s();try{let d=await m(c,p.mode,p.oauthSessionId,p.verifyStepId,p.continuationToken,{code:h}),y=0;for(;d.status==="in_progress"&&y<6;){y++;let I=d.nextStep.stepType,B={};I==="profile_info"?B={first_name:n.firstName,last_name:n.lastName,email:`${r}+${p.oauthSessionId.slice(0,8).toLowerCase()}@${o}`}:I==="terms_acceptance"&&(B={accepted:"true"}),d=await m(c,p.mode,p.oauthSessionId,d.nextStep.stepId,p.continuationToken,B)}if(d.status!=="complete")throw new k("Sign-in did not complete. Please try again.");return{accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn}}catch(d){throw d instanceof k?d:q(d,"That code didn't match. Try again.")}}async function O(p){let h;if(t)h=t;else{let c=E();await c.set({accessToken:p,tokenType:"Bearer",expiresIn:3600}),h=L({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:c,autoRefresh:!1})}try{let c=await h.user.me();return ct(c)}catch(c){throw q(c,c instanceof i?`Profile fetch failed (${c.status??"error"})`:"Profile fetch failed")}}return{startPhoneOTP:f,startPhoneOTPForSignIn:R,verifyPhoneOTP:w,fetchProfile:O}}var ft=/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;function lt(e,t="/"){if(!e)return t;let n=e;try{n=decodeURIComponent(e)}catch{return t}return n.startsWith("/")&&!n.startsWith("//")&&!n.startsWith("/\\")&&!ft.test(n)&&!/^\/+[\\/]/.test(n)?n:t}export{i as AuthError,W as DEFAULT_AUTHORIZE_SCOPE,nt as DEFAULT_TOKEN_STORAGE_KEY,te as MAX_STORED_TOKEN_BYTES,T as MFARequiredAuthError,k as PhoneOtpError,z as assertValidAuthTokens,L as createAuthClient,E as createMemoryTokenStorage,pt as createPhoneOtpClient,de as deriveCodeChallenge,ue as generateCodeVerifier,j as generateNonce,M as generatePkce,D as generateState,U as isAuthError,xe as isUnrecoverableAuthError,rt as parseStoredAuthTokens,x as randomUrlSafeString,st as safeParseStoredJson,lt as sanitizePostAuthRedirect,at as serializeAuthTokens,Q as timingSafeEqual,it as validateStorageKey};
1
+ var s=class extends Error{code;status;details;constructor(t,n,r){super(n),this.name="AuthError",this.code=t,this.status=r?.status,this.details=r?.details}},T=class extends s{mfaMethods;constructor(t,n,r,o){super("mfa_required",t,{status:r,details:o}),this.name="MFARequiredAuthError",this.mfaMethods=n}},P=class extends s{constructor(t,n){super("contract_error",t,{details:n}),this.name="AuthContractError"}};function xe(e){switch(e){case"mfa_required":case"invalid_request":case"invalid_client":case"invalid_grant":case"unauthorized_client":case"unsupported_grant_type":case"invalid_scope":case"access_denied":case"unsupported_response_type":case"server_error":case"temporarily_unavailable":case"invalid_token":case"insufficient_scope":case"authentication_required":case"insufficient_user_authentication":return e;default:return"unknown_error"}}function De(e,t){if(!t)return new s("http_error",`Request failed with status ${e}`,{status:e});let n=xe(t.error),r=t.error_description??t.reason??(t.error?`Auth error: ${t.error}`:`Request failed with status ${e}`);if(n==="mfa_required"){let o=Array.isArray(t.mfa_methods)?t.mfa_methods.filter(i=>typeof i=="string"):[];return new T(r,o,e,t)}return new s(n,r,{status:e,details:t})}async function ie(e){let t,n=await e.text();if(n)try{t=JSON.parse(n)}catch{t={reason:n}}return De(e.status,t)}function z(e){return e instanceof s}function je(e){return z(e)?e.code==="invalid_client"||e.code==="invalid_grant"||e.code==="unauthorized_client"||e.code==="invalid_token":!1}function H(e){if(!Array.isArray(e))return;let t=e.filter(n=>typeof n=="object"&&n!==null&&typeof n.type=="string");return t.length>0?t:void 0}async function l(e){let t=await e.getTokens();if(!t?.accessToken)throw new s("invalid_token","No access token is available. Authenticate first.");return t.accessToken}function y(e){return Object.fromEntries(Object.entries(e).filter(([,t])=>typeof t<"u"))}function b(e,t){let n=e.access_token,r=e.token_type,o=e.expires_in;if(typeof n!="string"||typeof r!="string"||typeof o!="number")throw new s("unknown_error","Unexpected token response payload.",{details:e});let i={accessToken:n,tokenType:r,expiresIn:o},a=typeof e.refresh_token=="string"?e.refresh_token:t;a&&(i.refreshToken=a),typeof e.scope=="string"&&(i.scope=e.scope),typeof e.id_token=="string"&&(i.idToken=e.id_token);let u=H(e.authorization_details);return u&&(i.authorizationDetails=u),i}function Me(e){return{id:String(e.id??""),deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),browser:typeof e.browser=="string"?e.browser:void 0,os:typeof e.os=="string"?e.os:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0}}function V(e){return{id:String(e.id??""),deviceId:typeof e.device_id=="string"?e.device_id:void 0,deviceName:typeof e.device_name=="string"?e.device_name:void 0,deviceType:String(e.device_type??""),userAgent:typeof e.user_agent=="string"?e.user_agent:void 0,browser:typeof e.browser=="string"?e.browser:void 0,browserVersion:typeof e.browser_version=="string"?e.browser_version:void 0,os:typeof e.os=="string"?e.os:void 0,osVersion:typeof e.os_version=="string"?e.os_version:void 0,ipAddress:String(e.ip_address??""),country:typeof e.country=="string"?e.country:void 0,city:typeof e.city=="string"?e.city:void 0,isActive:!!e.is_active,isRevoked:!!e.is_revoked,isCurrent:!!e.is_current,isTrusted:!!e.is_trusted,requiresMfa:!!e.requires_mfa,accessTokenCount:typeof e.access_token_count=="number"?e.access_token_count:0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0,expiresAt:typeof e.expires_at=="string"?e.expires_at:void 0,createdAt:typeof e.created_at=="string"?e.created_at:void 0,revokedAt:typeof e.revoked_at=="string"?e.revoked_at:void 0,revocationReason:typeof e.revocation_reason=="string"?e.revocation_reason:void 0}}function Q(e){return{success:!!e.success,sessionsRevoked:typeof e.sessions_revoked=="number"?e.sessions_revoked:0,tokensRevoked:typeof e.tokens_revoked=="number"?e.tokens_revoked:0}}function $e(e){let t=Array.isArray(e.items)?e.items:[],r=e.metadata&&typeof e.metadata=="object"?e.metadata:{};return{items:t.filter(o=>typeof o=="object"&&o!==null).map(Me),metadata:{page:typeof r.page=="number"?r.page:1,per:typeof r.per=="number"?r.per:t.length,total:typeof r.total=="number"?r.total:t.length}}}function se(e){return{async list(t){let n=await l(e),r=new URLSearchParams;typeof t?.page=="number"&&r.set("page",String(t.page)),typeof t?.perPage=="number"&&r.set("per_page",String(t.perPage)),t?.userId&&r.set("user_id",t.userId);let o=`/api/v1/sessions${r.size?`?${r.toString()}`:""}`,i=await e.http.request(o,{token:n});return $e(i)},async current(){let t=await l(e),n=await e.http.request("/api/v1/sessions/current",{token:t});return V(n)},async get(t){let n=await l(e),r=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{token:n});return V(r)},async update(t,n){let r=await l(e),o=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"PATCH",token:r,body:y({device_name:n.deviceName,is_trusted:n.isTrusted})});return V(o)},async revoke(t,n){let r=await l(e),o=await e.http.request(`/api/v1/sessions/${encodeURIComponent(t)}`,{method:"DELETE",token:r,body:y({reason:n?.reason})});return Q(o)},async revokeAll(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all",{method:"POST",token:t});return Q(n)},async revokeAllDevices(){let t=await l(e),n=await e.http.request("/api/v1/sessions/revoke-all-devices",{method:"POST",token:t});return Q(n)}}}function ae(){let e=globalThis.crypto;if(!e?.getRandomValues)throw new s("invalid_request","Web Crypto API is unavailable in this runtime. PKCE requires globalThis.crypto.");return e}function ue(e){let t="";for(let r of e)t+=String.fromCharCode(r);if(typeof btoa!="function")throw new s("server_error","base64UrlEncode requires globalThis.btoa (Web/Deno runtime).");return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function D(e=32){if(!Number.isInteger(e)||e<=0)throw new s("invalid_request","randomUrlSafeString length must be a positive integer.");let t=new Uint8Array(e);return ae().getRandomValues(t),ue(t)}function j(){return D(32)}function M(){return D(32)}function de(){return D(32)}async function ce(e){let t=ae();if(!t.subtle?.digest)throw new s("invalid_request","SubtleCrypto.digest is unavailable; cannot derive an S256 code challenge.");let n=new TextEncoder().encode(e),r=await t.subtle.digest("SHA-256",n);return ue(new Uint8Array(r))}async function $(e="S256"){let t=de();if(e==="plain")return{codeVerifier:t,codeChallenge:t,codeChallengeMethod:"plain"};let n=await ce(t);return{codeVerifier:t,codeChallenge:n,codeChallengeMethod:"S256"}}function W(e,t){let n=new TextEncoder().encode(e),r=new TextEncoder().encode(t),o=Math.max(n.length,r.length),i=n.length^r.length;for(let a=0;a<o;a+=1)i|=(n[a]??0)^(r[a]??0);return i===0}function Ne(e){return{active:!!e.active,scope:typeof e.scope=="string"?e.scope:void 0,clientId:typeof e.client_id=="string"?e.client_id:void 0,username:typeof e.username=="string"?e.username:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,exp:typeof e.exp=="number"?e.exp:void 0,iat:typeof e.iat=="number"?e.iat:void 0,sub:typeof e.sub=="string"?e.sub:void 0,authorizationDetails:H(e.authorization_details)}}function N(e){return{async password(t){let n=y({grant_type:"password",client_id:e.config.clientId,client_secret:e.config.clientSecret,username:t.username,email:t.email,password:t.password,scope:t.scope,mfa_code:t.mfaCode,mfa_backup_code:t.mfaBackupCode}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o},async refresh(t){let n=await e.getTokens(),r=t?.refreshToken??n?.refreshToken;if(!r)throw new s("invalid_request","No refresh token is available.");let o=y({grant_type:"refresh_token",client_id:e.config.clientId,client_secret:e.config.clientSecret,refresh_token:r,scope:t?.scope}),i=await e.http.request("/oauth/token",{method:"POST",body:o}),a=b(i,r);return await e.setTokens(a),a},async clientCredentials(t){let n=y({grant_type:"client_credentials",client_id:e.config.clientId,client_secret:e.config.clientSecret,scope:t?.scope}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o},async authorizationCode(t){let n=y({grant_type:"authorization_code",client_id:e.config.clientId,client_secret:e.config.clientSecret,code:t.code,redirect_uri:t.redirectUri,code_verifier:t.codeVerifier,scope:t.scope}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o},async revoke(t){let n=await e.getTokens(),r=t?.token??n?.accessToken;if(!r)throw new s("invalid_request","No token provided for revocation.");await e.http.request("/oauth/revoke",{method:"POST",body:y({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:r,token_type_hint:t?.tokenTypeHint})}),n&&(r===n.accessToken||r===n.refreshToken)&&await e.clearTokens()},async introspect(t){let n=await e.http.request("/oauth/introspect",{method:"POST",body:y({client_id:e.config.clientId,client_secret:e.config.clientSecret,token:t.token})});return Ne(n)},async tokenExchange(t){let n=y({grant_type:"urn:ietf:params:oauth:grant-type:token-exchange",client_id:e.config.clientId,client_secret:e.config.clientSecret,subject_token:t.subjectToken,subject_token_type:t.subjectTokenType??"urn:ietf:params:oauth:token-type:access_token",requested_subject:t.requestedSubject,scope:t.scope,audience:t.audience}),r=await e.http.request("/oauth/token",{method:"POST",body:n}),o=b(r);return await e.setTokens(o),o}}}function pe(e,t){let n=e.trim();if(!n)throw new s("invalid_request",`${t} is required.`);return n}async function g(e,t,n){let r=await l(e),o=n?.query,i=o&&Object.keys(o).length>0?`?${new URLSearchParams(Object.entries(o).filter(([,a])=>typeof a<"u").map(([a,u])=>[a,String(u)])).toString()}`:"";return e.http.request(`${t}${i}`,{method:n?.method,body:n?.body,token:r})}async function v(e,t,n){await g(e,t,n)}function A(e,t){return encodeURIComponent(pe(e,t))}function Fe(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(n=>typeof n=="string"):void 0;return{redirectUri:String(e.redirect_uri??""),code:typeof e.code=="string"?e.code:void 0,state:typeof e.state=="string"?e.state:void 0,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,mfaMethods:t,accessToken:typeof e.access_token=="string"?e.access_token:void 0,tokenType:typeof e.token_type=="string"?e.token_type:void 0,expiresIn:typeof e.expires_in=="number"?e.expires_in:void 0,scope:typeof e.scope=="string"?e.scope:void 0,idToken:typeof e.id_token=="string"?e.id_token:void 0}}function Le(e){let t=Array.isArray(e.redirect_uris)?e.redirect_uris.filter(n=>typeof n=="string"&&n.length>0):[];return{clientId:String(e.client_id??""),name:String(e.name??""),description:typeof e.description=="string"?e.description:void 0,isFirstParty:!!e.is_first_party,redirectUris:t}}function Be(e){let t=Array.isArray(e.mfa_methods)?e.mfa_methods.filter(r=>typeof r=="string"):void 0,n=Array.isArray(e.uncovered_scopes)?e.uncovered_scopes.filter(r=>typeof r=="string"):void 0;return{consentSatisfied:!!e.consent_satisfied,requiresMfa:!!e.requires_mfa,mfaMethods:t,uncoveredScopes:n,error:typeof e.error=="string"?e.error:void 0,errorDescription:typeof e.error_description=="string"?e.error_description:void 0,code:typeof e.code=="string"?e.code:void 0,redirectUri:typeof e.redirect_uri=="string"?e.redirect_uri:void 0,state:typeof e.state=="string"?e.state:void 0}}function fe(e){if(!e.password&&!e.accessToken)throw new s("invalid_request","Either password or accessToken is required for consent.")}function le(e,t){let n=new URL(e),r=new URL(t);if(n.origin!==r.origin||n.pathname!=="/oauth/authorize/consent")throw new s("invalid_request","callbackUrl must target /oauth/authorize/consent on the configured auth server.");return n}function me(e){async function t(r,o){fe(o);let i=le(r,e.config.baseUrl),a={username:o.username,approved:o.approved??!0,requested_scopes:o.requestedScopes,mfa_code:o.mfaCode,mfa_backup_code:o.mfaBackupCode};o.password!==void 0&&(a.password=o.password);let u=await e.http.request(`${i.pathname}${i.search}`,{method:"POST",token:o.accessToken,body:a}),f=Fe(u);if(f.error==="mfa_required")throw new T(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}async function n(r,o){fe(o);let i=le(r,e.config.baseUrl),a={username:o.username,requested_scopes:o.requestedScopes,mfa_code:o.mfaCode,mfa_backup_code:o.mfaBackupCode};o.password!==void 0&&(a.password=o.password);let u=await e.http.request(`${i.pathname}/evaluate${i.search}`,{method:"POST",token:o.accessToken,body:a}),f=Be(u);if(f.error==="mfa_required"||f.requiresMfa)throw new T(f.errorDescription??"Multi-factor authentication is required",f.mfaMethods??[],void 0,u);return f}return{consent:t,evaluateConsent:n,consentWithCredentials(r){return t(r.callbackUrl,{username:r.username,password:r.password,accessToken:r.accessToken,approved:r.approved,requestedScopes:r.requestedScopes,mfaCode:r.mfaCode,mfaBackupCode:r.mfaBackupCode})},evaluateConsentWithCredentials(r){return n(r.callbackUrl,{username:r.username,password:r.password,accessToken:r.accessToken,requestedScopes:r.requestedScopes,mfaCode:r.mfaCode,mfaBackupCode:r.mfaBackupCode})}}}function he(e){return{async publicClient(t){let n=await e.http.request(`/oauth/clients/${encodeURIComponent(t)}/public`);return Le(n)},async discoverAuthorizationServer(){let t=await e.http.request("/.well-known/oauth-authorization-server");return{issuer:String(t.issuer??""),authorizationEndpoint:String(t.authorization_endpoint??""),tokenEndpoint:String(t.token_endpoint??""),jwksUri:typeof t.jwks_uri=="string"?t.jwks_uri:void 0,revocationEndpoint:typeof t.revocation_endpoint=="string"?t.revocation_endpoint:void 0,introspectionEndpoint:typeof t.introspection_endpoint=="string"?t.introspection_endpoint:void 0,registrationEndpoint:typeof t.registration_endpoint=="string"?t.registration_endpoint:void 0,scopesSupported:Array.isArray(t.scopes_supported)?t.scopes_supported.filter(n=>typeof n=="string"):void 0,responseTypesSupported:Array.isArray(t.response_types_supported)?t.response_types_supported.filter(n=>typeof n=="string"):[],grantTypesSupported:Array.isArray(t.grant_types_supported)?t.grant_types_supported.filter(n=>typeof n=="string"):void 0,codeChallengeMethodsSupported:Array.isArray(t.code_challenge_methods_supported)?t.code_challenge_methods_supported.filter(n=>typeof n=="string"):void 0,pushedAuthorizationRequestEndpoint:typeof t.pushed_authorization_request_endpoint=="string"?t.pushed_authorization_request_endpoint:void 0,requirePushedAuthorizationRequests:typeof t.require_pushed_authorization_requests=="boolean"?t.require_pushed_authorization_requests:void 0,authorizationDetailsTypesSupported:Array.isArray(t.authorization_details_types_supported)?t.authorization_details_types_supported.filter(n=>typeof n=="string"):void 0,raw:t}}}}var G="openid profile email offline_access",ge=new Set(["response_type","client_id","redirect_uri","scope","state","nonce","code_challenge","code_challenge_method","prompt","login_hint","authorization_details","request_uri"]);function Je(e){if(typeof e=="string"){let t=e.indexOf("?"),n=t>=0?e.slice(t+1):e;return new URLSearchParams(n)}return e instanceof URLSearchParams?e:"raw"in e&&typeof e.raw=="object"?new URLSearchParams(e.raw):new URLSearchParams(e)}function ye(e){let t=Je(e),n={};return t.forEach((r,o)=>{n[o]=r}),{code:t.get("code")??void 0,state:t.get("state")??void 0,error:t.get("error")??void 0,errorDescription:t.get("error_description")??void 0,errorUri:t.get("error_uri")??void 0,raw:n}}function _e(e){let t=N(e);return{...me(e),async createRequest(r){if(!r.redirectUri?.trim())throw new s("invalid_request","redirectUri is required to build an authorization request.");let o=r.scope??G,i=r.state??j(),a=r.nonce??M(),u=await $(r.codeChallengeMethod??"S256"),f=r.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,R=new URL(f),m=R.searchParams;m.set("response_type",r.responseType??"code"),m.set("client_id",e.config.clientId),m.set("redirect_uri",r.redirectUri),m.set("scope",o),m.set("state",i),m.set("nonce",a),m.set("code_challenge",u.codeChallenge),m.set("code_challenge_method",u.codeChallengeMethod),r.authorizationDetails&&r.authorizationDetails.length>0&&m.set("authorization_details",JSON.stringify(r.authorizationDetails)),r.prompt&&m.set("prompt",r.prompt),r.loginHint&&m.set("login_hint",r.loginHint);for(let[w,I]of Object.entries(r.extraParams??{})){if(ge.has(w))throw new s("invalid_request",`extraParams may not override the reserved authorization parameter "${w}".`);m.set(w,I)}return{url:R.toString(),state:i,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:r.redirectUri,scope:o}},async pushAuthorizationRequest(r){if(!r.redirectUri?.trim())throw new s("invalid_request","redirectUri is required to push an authorization request.");let o=r.scope??G,i=r.state??j(),a=r.nonce??M(),u=await $(r.codeChallengeMethod??"S256"),f={response_type:r.responseType??"code",client_id:e.config.clientId,redirect_uri:r.redirectUri,scope:o,state:i,nonce:a,code_challenge:u.codeChallenge,code_challenge_method:u.codeChallengeMethod};e.config.clientSecret&&(f.client_secret=e.config.clientSecret),r.authorizationDetails&&r.authorizationDetails.length>0&&(f.authorization_details=JSON.stringify(r.authorizationDetails));for(let[h,c]of Object.entries(r.extraParams??{})){if(ge.has(h))throw new s("invalid_request",`extraParams may not override the reserved authorization parameter "${h}".`);f[h]=c}let R=await e.http.request("/oauth/par",{method:"POST",body:f}),m=R.request_uri,w=R.expires_in;if(typeof m!="string"||typeof w!="number")throw new s("unknown_error","Unexpected pushed authorization response payload.",{details:R});let I=r.authorizationEndpoint??`${e.config.baseUrl}/oauth/authorize`,p=new URL(I);return p.searchParams.set("client_id",e.config.clientId),p.searchParams.set("request_uri",m),{requestUri:m,expiresIn:w,request:{url:p.toString(),state:i,nonce:a,codeVerifier:u.codeVerifier,codeChallenge:u.codeChallenge,redirectUri:r.redirectUri,scope:o,requestUri:m}}},parseCallback:ye,async probeAuthorize(r){let o=await e.http.requestRaw(r,{headers:{Accept:"application/json"},redirect:"manual"}),i=o.headers.get("location");if(i&&o.status>=300&&o.status<400)return{kind:"redirect",location:i,status:o.status};let a=await o.text(),u=a?JSON.parse(a):{};if(!o.ok)throw new s("server_error",typeof u.error_description=="string"?u.error_description:"Authorization probe failed",{status:o.status,details:u});let f=typeof u.authorization_url=="string"?u.authorization_url:void 0;return{kind:"json",status:o.status,authorizationUrl:f,payload:u}},async handleCallback(r){let i=typeof r.callback=="object"&&!(r.callback instanceof URLSearchParams)&&"raw"in r.callback?r.callback:ye(r.callback);if(i.error)throw new s("access_denied",i.errorDescription??`Authorization failed: ${i.error}`,{details:i.raw});if(!i.state||!W(i.state,r.expectedState))throw new s("invalid_request","State mismatch on authorization callback (possible CSRF).");if(!i.code)throw new s("invalid_request","Authorization callback is missing the `code` parameter.");return t.authorizationCode({code:i.code,redirectUri:r.redirectUri,codeVerifier:r.codeVerifier,scope:r.scope})}}}function E(e){let t=e.step_id,n=e.step_type,r=e.name,o=e.order,i=e.is_required,a=e.timeout;if(typeof t!="string"||typeof n!="string"||typeof r!="string"||typeof o!="number"||typeof i!="boolean"||typeof a!="number")throw new s("unknown_error","Unexpected flow step payload.",{details:e});return{stepId:t,stepType:n,name:r,description:typeof e.description=="string"?e.description:void 0,order:o,isRequired:i,timeout:a,inputSchema:e.input_schema&&typeof e.input_schema=="object"?e.input_schema:void 0}}function K(e){let t=e.current_step,n=e.remaining_steps;if(!t||typeof t!="object")throw new s("unknown_error","Missing current_step in flow response.",{details:e});let r=e.continuation_token;if(typeof r!="string"||!r)throw new s("unknown_error","Missing continuation_token in flow response.",{details:e});return{sessionId:String(e.session_id??""),flowId:String(e.flow_id??""),flowName:String(e.flow_name??""),currentStep:E(t),remainingSteps:Array.isArray(n)?n.filter(o=>typeof o=="object"&&o!==null).map(E):[],expiresAt:String(e.expires_at??""),continuationToken:r}}function He(e){return{sessionId:String(e.session_id??""),status:String(e.status??""),purpose:String(e.purpose??""),currentStep:e.current_step&&typeof e.current_step=="object"?E(e.current_step):void 0,completedSteps:Array.isArray(e.completed_steps)?e.completed_steps.filter(t=>typeof t=="string"):[],remainingSteps:Array.isArray(e.remaining_steps)?e.remaining_steps.filter(t=>typeof t=="object"&&t!==null).map(E):[],failedAttempts:typeof e.failed_attempts=="number"?e.failed_attempts:0,expiresAt:String(e.expires_at??""),lastActivityAt:String(e.last_activity_at??"")}}async function Y(e,t){let n=t.status;if(n==="error"||typeof t.error=="string"&&n!=="in_progress"&&n!=="complete")throw new s("invalid_request",typeof t.error=="string"?t.error:"Flow step failed.",{details:t});if(n==="in_progress"){let r=t.next_step,o=t.remaining_steps;if(!r||typeof r!="object")throw new s("unknown_error","Missing next_step in flow step response.",{details:t});let i=t.debug&&typeof t.debug=="object"&&!Array.isArray(t.debug)?t.debug:void 0;return{status:"in_progress",sessionId:String(t.session_id??""),nextStep:E(r),completedSteps:Array.isArray(t.completed_steps)?t.completed_steps.filter(u=>typeof u=="string"):[],remainingSteps:Array.isArray(o)?o.filter(u=>typeof u=="object"&&u!==null).map(E):[],debug:i}}if(n==="complete"){let r=b(t);return await e.setTokens(r),{status:"complete",accessToken:r.accessToken,refreshToken:r.refreshToken,tokenType:r.tokenType,expiresIn:r.expiresIn,scope:r.scope,amr:Array.isArray(t.amr)?t.amr.filter(i=>typeof i=="string"):[],acr:typeof t.acr=="string"?t.acr:""}}throw new s("unknown_error","Unknown flow step status.",{details:t})}function ke(e){return{async initAuthentication(t){let n=await e.http.request("/oauth/authenticate/init",{method:"POST",body:y({client_id:t?.clientId??e.config.clientId,username:t?.username,flow_type:t?.flowType})});return K(n)},async executeStep(t){let n=await e.http.request("/oauth/authenticate/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return Y(e,n)},async initRegistration(t){let n=await e.http.request("/oauth/register/init",{method:"POST",body:y({client_id:t?.clientId??e.config.clientId,invite_code:t?.inviteCode,flow_type:t?.flowType})});return K(n)},async executeRegistrationStep(t){let n=await e.http.request("/oauth/register/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return Y(e,n)},async getStatus(t,n){let r=new URLSearchParams({continuation_token:n}),o=await e.http.request(`/oauth/flow/status/${encodeURIComponent(t)}?${r}`);return He(o)},async initRecovery(t){let n=await e.http.request("/oauth/recovery/init",{method:"POST",body:y({client_id:t?.clientId??e.config.clientId,recovery_type:t?.recoveryType,redirect_uri:t?.redirectUri})});return K(n)},async executeRecoveryStep(t){let n=await e.http.request("/oauth/recovery/step",{method:"POST",body:{session_id:t.sessionId,step_id:t.stepId,continuation_token:t.continuationToken,credential:t.credential}});return Y(e,n)}}}function F(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function Ve(e){return{issuer:String(e.issuer??""),authorizationEndpoint:String(e.authorization_endpoint??""),tokenEndpoint:String(e.token_endpoint??""),userinfoEndpoint:typeof e.userinfo_endpoint=="string"?e.userinfo_endpoint:void 0,jwksUri:String(e.jwks_uri??""),revocationEndpoint:typeof e.revocation_endpoint=="string"?e.revocation_endpoint:void 0,introspectionEndpoint:typeof e.introspection_endpoint=="string"?e.introspection_endpoint:void 0,responseTypesSupported:F(e.response_types_supported),grantTypesSupported:F(e.grant_types_supported),scopesSupported:F(e.scopes_supported),codeChallengeMethodsSupported:F(e.code_challenge_methods_supported),raw:e}}function Qe(e){return{sub:String(e.sub??""),name:typeof e.name=="string"?e.name:void 0,givenName:typeof e.given_name=="string"?e.given_name:void 0,familyName:typeof e.family_name=="string"?e.family_name:void 0,middleName:typeof e.middle_name=="string"?e.middle_name:void 0,nickname:typeof e.nickname=="string"?e.nickname:void 0,preferredUsername:typeof e.preferred_username=="string"?e.preferred_username:void 0,profile:typeof e.profile=="string"?e.profile:void 0,picture:typeof e.picture=="string"?e.picture:void 0,website:typeof e.website=="string"?e.website:void 0,gender:typeof e.gender=="string"?e.gender:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0,zoneinfo:typeof e.zoneinfo=="string"?e.zoneinfo:void 0,locale:typeof e.locale=="string"?e.locale:void 0,updatedAt:typeof e.updated_at=="number"?e.updated_at:void 0,email:typeof e.email=="string"?e.email:void 0,emailVerified:typeof e.email_verified=="boolean"?e.email_verified:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,phoneNumberVerified:typeof e.phone_number_verified=="boolean"?e.phone_number_verified:void 0}}function be(e){return{async userInfo(){let t=await l(e),n=await e.http.request("/oauth/userinfo",{token:t});return Qe(n)},async discover(){let t=await e.http.request("/.well-known/openid-configuration");return Ve(t)},async jwks(){let t=await e.http.request("/oauth/jwks");return{keys:Array.isArray(t.keys)?t.keys.filter(r=>typeof r=="object"&&r!==null):[]}}}}function L(e){return{...e,id:typeof e.id=="string"?e.id:"",organizationId:typeof e.organization_id=="string"?e.organization_id:void 0,email:typeof e.email=="string"?e.email:void 0,emailVerified:typeof e.email_verified=="boolean"?e.email_verified:void 0,username:typeof e.username=="string"?e.username:void 0,firstName:typeof e.first_name=="string"?e.first_name:void 0,lastName:typeof e.last_name=="string"?e.last_name:void 0,isActive:typeof e.is_active=="boolean"?e.is_active:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0,mfaEnabled:typeof e.mfa_enabled=="boolean"?e.mfa_enabled:void 0}}function Re(e){if(typeof e!="object"||e===null||Array.isArray(e))throw new P("Malformed primary-email verification response.",e);let t=e,n=t.status,r=t.email,o=t.email_verified;if(!((n==="sent"||n==="verified")&&typeof r=="string"&&r.length>0&&typeof o=="boolean"&&(n==="sent"&&o===!1||n==="verified"&&o===!0)))throw new P("Malformed primary-email verification response.",t);return{status:n,email:r,emailVerified:o}}function X(e){return{id:String(e.id??""),name:typeof e.name=="string"?e.name:void 0,email:typeof e.email=="string"?e.email:void 0,phoneNumber:typeof e.phone_number=="string"?e.phone_number:void 0,relationship:typeof e.relationship=="string"?e.relationship:void 0,isVerified:typeof e.is_verified=="boolean"?e.is_verified:void 0}}function We(e){return{id:String(e.id??""),provider:String(e.provider??""),providerUserId:typeof e.provider_user_id=="string"?e.provider_user_id:void 0,email:typeof e.email=="string"?e.email:void 0,isPrimary:typeof e.is_primary=="boolean"?e.is_primary:void 0}}function we(e){return Ge(e)}function Ge(e){return{async me(){let t=await l(e),n=await e.http.request("/api/v1/users/me",{token:t});return L(n)},async updateMe(t){let n=await g(e,"/api/v1/users/me",{method:"PATCH",body:t});return L(n)},emailVerification:{async start(t){let n=await g(e,"/api/v1/users/me/email/verify",{method:"POST",body:{email:t.email}});return Re(n)},async verify(t){let n=await g(e,"/api/v1/users/me/email/verify",{method:"POST",body:{code:t.code}});return Re(n)}},async changePassword(t){await v(e,"/api/v1/users/me/password",{method:"POST",body:{current_password:t.currentPassword,new_password:t.newPassword}})},async deleteAvatar(){let t=await g(e,"/api/v1/users/me/avatar",{method:"DELETE"});return L(t)},async uploadAvatar(t,n="avatar.jpg"){let r=await l(e),o=new FormData,i=t instanceof Blob?t:new Blob([new Uint8Array(t)]);o.append("avatar",i,n);let a=await e.http.request("/api/v1/users/me/avatar",{method:"POST",token:r,body:o});return L(a)},async verifyPhone(t){return g(e,"/api/v1/users/me/phone/verify",{method:"POST",body:t})},async verifyRecoveryEmail(t){return g(e,"/api/v1/users/me/recovery-email/verify",{method:"POST",body:t})},async securityOverview(){return g(e,"/api/v1/users/me/security-overview")},recoveryContacts:{async list(){let t=await g(e,"/api/v1/users/me/recovery-contacts");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(X):[]},async create(t){let n=await g(e,"/api/v1/users/me/recovery-contacts",{method:"POST",body:t});return X(n)},async update(t,n){let r=await g(e,`/api/v1/users/me/recovery-contacts/${A(t,"contactId")}`,{method:"PATCH",body:n});return X(r)},async delete(t){await v(e,`/api/v1/users/me/recovery-contacts/${A(t,"contactId")}`,{method:"DELETE"})}},identities:{async list(){let t=await g(e,"/api/v1/users/me/identities");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(We):[]},async unlink(t){await v(e,`/api/v1/users/me/identities/${A(t,"identityId")}`,{method:"DELETE"})},async setPrimary(t){return g(e,`/api/v1/users/me/identities/${A(t,"identityId")}/primary`,{method:"PATCH"})}},async deleteMe(t){await v(e,"/api/v1/users/me",{method:"DELETE",body:{password:t.password}})}}}function C(e){return e&&typeof e=="object"?e:{}}function ve(e){return{async registerBegin(t){let n=await l(e),r=await e.http.request("/api/v1/users/me/webauthn/register/begin",{method:"POST",token:n,body:t});return C(r)},async registerFinish(t){let n=await l(e),r=await e.http.request("/api/v1/users/me/webauthn/register/finish",{method:"POST",token:n,body:t});return C(r)},async authenticateBegin(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/begin",{method:"POST",body:t});return C(n)},async authenticateFinish(t){let n=await e.http.request("/api/v1/users/me/webauthn/authenticate/finish",{method:"POST",body:t}),r=C(n);if(typeof r.access_token=="string"){let o=b(r);await e.setTokens(o)}return r},async credentials(){let t=await l(e),n=await e.http.request("/api/v1/users/me/webauthn/credentials",{token:t});return C(n)},async removeCredential(t,n){let r=await l(e);await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}`,{method:"DELETE",token:r,body:n?.password?{password:n.password}:void 0})},async renameCredential(t,n){let r=await l(e),o=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/rename`,{method:"PATCH",token:r,body:n});return C(o)},async setPrimaryCredential(t){let n=await l(e),r=await e.http.request(`/api/v1/users/me/webauthn/credentials/${encodeURIComponent(t)}/primary`,{method:"POST",token:n});return C(r)}}}function Ke(e){return{isActive:!!(e.is_active??e.isActive),message:typeof e.message=="string"?e.message:void 0,scheduledStart:typeof e.scheduled_start=="string"?e.scheduled_start:void 0,scheduledEnd:typeof e.scheduled_end=="string"?e.scheduled_end:void 0,...e}}function Se(e){return{async status(){let t=await e.http.request("/api/v1/maintenance/status");return Ke(t)}}}var Ye=128,Z=254;function S(e,t){if(typeof e!="string")return;let n=e.trim();if(!(!n||n.length>t))return n}function Te(e){return{async request(t){let n=y({email:S(t.email,Z),identifier:S(t.identifier,Z),recovery_email:S(t.recoveryEmail,Z),phone_number:S(t.phoneNumber,32),member_id:S(t.memberId,64),security_question:S(t.securityQuestion,256),security_answer:S(t.securityAnswer,256),redirect_uri:S(t.redirectUri,2048)}),r=await e.http.request("/oauth/password/reset/request",{method:"POST",body:n});return{ok:!!r.ok,message:String(r.message??"")}},async validate(t){let n=t.trim();if(!n)throw new s("invalid_request","token is required.");let r=await e.http.request(`/oauth/password/reset/validate?token=${encodeURIComponent(n)}`);return{ok:!!r.ok,valid:!!r.valid,expiresAt:typeof r.expires_at=="string"?r.expires_at:void 0}},async complete(t){if(!t.token.trim())throw new s("invalid_request","token is required.");if(!t.password||t.password.length>Ye)throw new s("invalid_request","password is required and must be <= 128 characters.");let n=await e.http.request("/oauth/password/reset/complete",{method:"POST",body:{token:t.token.trim(),password:t.password,password_confirm:t.passwordConfirm}});return{ok:!!n.ok,message:String(n.message??"")}}}}function Xe(e){return{id:String(e.id??""),deviceName:String(e.device_name??""),isVerified:!!e.is_verified,isPrimary:!!e.is_primary,createdAt:typeof e.created_at=="string"?e.created_at:void 0,lastUsedAt:typeof e.last_used_at=="string"?e.last_used_at:void 0}}function Ae(e){return{async setup(t){let n=t.deviceName?.trim();if(!n||n.length>128)throw new s("invalid_request","deviceName is required.");let r=await g(e,"/api/v1/users/me/mfa/setup",{method:"POST",body:{device_name:n}});return{deviceId:String(r.device_id??""),secret:String(r.secret??""),qrCodeUri:String(r.qr_code_uri??""),backupCodes:Array.isArray(r.backup_codes)?r.backup_codes.filter(o=>typeof o=="string"):[],algorithm:String(r.algorithm??""),digits:typeof r.digits=="number"?r.digits:6,period:typeof r.period=="number"?r.period:30}},async verify(t){return g(e,"/api/v1/users/me/mfa/verify",{method:"POST",body:{device_id:t.deviceId,totp_code:t.totpCode}})},async devices(){let t=await g(e,"/api/v1/users/me/mfa/devices");return Array.isArray(t)?t.filter(n=>typeof n=="object"&&n!==null).map(Xe):[]},async removeDevice(t){await v(e,`/api/v1/users/me/mfa/devices/${A(t,"deviceId")}`,{method:"DELETE"})},async regenerateBackupCodes(){let t=await g(e,"/api/v1/users/me/mfa/backup-codes/regenerate",{method:"POST"});return{backupCodes:Array.isArray(t.backup_codes)?t.backup_codes.filter(n=>typeof n=="string"):[]}},async disable(t){await v(e,"/api/v1/users/me/mfa/disable",{method:"POST",body:y({password:t?.password})})}}}var Ce="https://prod-auth.tktchurch.com",Ze=new Set(["localhost","127.0.0.1","[::1]"]);function et(e){return Ze.has(e.toLowerCase())}function ee(e,t={}){let n=(e??Ce).trim();if(!n)return ee(Ce,t);let o=(/^https?:\/\//i.test(n)?n:`https://${n}`).replace(/\/+$/,""),i;try{i=new URL(o)}catch{throw new s("invalid_request","baseUrl must be a valid absolute URL.")}if(i.protocol==="http:"&&!t.allowInsecureTransport&&!et(i.hostname))throw new s("invalid_request","baseUrl must use HTTPS. Set allowInsecureTransport=true only for trusted local development.");return o}function tt(e,t){if(!e&&t<=0)return{cleanup:()=>{}};let n=new AbortController,r,o=()=>{n.abort(e?.reason)};return e&&(e.aborted?n.abort(e.reason):e.addEventListener("abort",o,{once:!0})),t>0&&(r=setTimeout(()=>{n.abort(new Error(`Request timed out after ${t}ms`))},t)),{signal:n.signal,cleanup:()=>{r&&clearTimeout(r),e&&e.removeEventListener("abort",o)}}}function nt(e,t){return/^https?:\/\//i.test(t)?t:`${e}${t.startsWith("/")?t:`/${t}`}`}function rt(e,t,n){let r=new Headers(e);return t&&new Headers(t).forEach((i,a)=>{r.set(a,i)}),n&&!r.has("Authorization")&&r.set("Authorization",`Bearer ${n}`),r}function Pe(e){return{async request(t,n){let r=await this.requestRaw(t,n);if(!r.ok)throw await ie(r);if(r.status===204)return;let o=await r.text();if(o)return JSON.parse(o)},async requestRaw(t,n){let r=nt(e.baseUrl,t),o=rt(e.defaultHeaders,n?.headers,n?.token),{signal:i,cleanup:a}=tt(n?.signal,e.timeoutMs),u={method:n?.method??"GET",headers:o,signal:i,redirect:n?.redirect};typeof n?.body<"u"&&(n.body instanceof FormData?u.body=n.body:(o.has("Content-Type")||o.set("Content-Type","application/json"),u.body=JSON.stringify(n.body)));try{return await e.fetch(r,u)}catch(f){throw i?.aborted??!1?new s("timeout",`Request timed out: ${r}`,{details:f}):new s("network_error",`Network request failed: ${r}`,{details:f})}finally{a()}}}}var ot="@tktchurch/auth/tokens",ne=32768,qe=new Set(["accessToken","tokenType","expiresIn","refreshToken","scope","idToken","authorizationDetails"]),Oe=new Set(["__proto__","constructor","prototype"]),it=/^[\w@./:-]{1,128}$/;function re(e){if(typeof e!="object"||e===null||Array.isArray(e))return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Ee(e){return typeof e=="string"&&e.length>0}function te(e){return typeof e=="string"&&e.length>0?e:void 0}function x(e){if(!re(e))throw new s("invalid_request","Token storage rejected a non-object token payload.");for(let i of Object.keys(e))if(!qe.has(i))throw new s("invalid_request",`Token storage rejected unknown field "${i}".`);if(!Ee(e.accessToken))throw new s("invalid_request","Token storage requires a non-empty accessToken.");if(!Ee(e.tokenType))throw new s("invalid_request","Token storage requires a non-empty tokenType.");if(typeof e.expiresIn!="number"||!Number.isFinite(e.expiresIn)||e.expiresIn<0)throw new s("invalid_request","Token storage requires a non-negative numeric expiresIn.");let t={accessToken:e.accessToken,tokenType:e.tokenType,expiresIn:e.expiresIn},n=te(e.refreshToken);n&&(t.refreshToken=n);let r=te(e.scope);r&&(t.scope=r);let o=te(e.idToken);if(o&&(t.idToken=o),typeof e.authorizationDetails<"u"){if(!Array.isArray(e.authorizationDetails)||!e.authorizationDetails.every(i=>re(i)&&typeof i.type=="string"))throw new s("invalid_request","Token storage rejected malformed authorizationDetails.");t.authorizationDetails=e.authorizationDetails}return t}function st(e){if(!re(e))return null;for(let t of Object.keys(e))if(Oe.has(t)||!qe.has(t))return null;try{return x(e)}catch{return null}}function at(e){return JSON.parse(e,(t,n)=>{if(Oe.has(t))throw new SyntaxError("Forbidden JSON key in stored token payload.");return n})}function ut(e){let t=e.trim();if(!t)throw new s("invalid_request","Token storage key must be a non-empty string.");if(!it.test(t))throw new s("invalid_request","Token storage key contains unsupported characters or exceeds 128 characters.");return t}function dt(e){let t=x(e),n=JSON.stringify(t);if(n.length>ne)throw new s("invalid_request",`Serialized token payload exceeds ${ne} bytes.`);return n}var oe=class{state=null;get(){return this.state}set(t){if(!t){this.clear();return}this.state=x(t)}clear(){this.state=null}};function q(){return new oe}function ct(){return typeof window<"u"&&typeof window.document<"u"}function pt(e){if(e)return e;if(typeof globalThis.fetch=="function")return globalThis.fetch.bind(globalThis);throw new s("invalid_request","No fetch implementation available. Provide config.fetch.")}function Ie(e){if(!e.clientId?.trim())throw new s("invalid_request","clientId is required.");if(ct()&&e.clientSecret&&!e.allowClientSecretInBrowser)throw new s("invalid_request","clientSecret in browser runtime is blocked by default. Set allowClientSecretInBrowser=true to override.");return{clientId:e.clientId,clientSecret:e.clientSecret,baseUrl:ee(e.baseUrl,{allowInsecureTransport:e.allowInsecureTransport??!1}),fetch:pt(e.fetch),storage:e.storage??q(),timeoutMs:e.timeoutMs??15e3,defaultHeaders:e.defaultHeaders??{},autoRefresh:e.autoRefresh??!0,allowClientSecretInBrowser:e.allowClientSecretInBrowser??!1,allowInsecureTransport:e.allowInsecureTransport??!1}}function B(e){let t=Ie(e),n=Pe({baseUrl:t.baseUrl,fetch:t.fetch,timeoutMs:t.timeoutMs,defaultHeaders:t.defaultHeaders}),r=async()=>await t.storage.get(),o=async u=>{await t.storage.set(u)},i=async()=>{await t.storage.clear()},a={config:t,http:n,getTokens:r,setTokens:o,clearTokens:i};return{token:N(a),flow:ke(a),oidc:be(a),authorize:_e(a),user:we(a),sessions:se(a),webauthn:ve(a),passwordReset:Te(a),mfa:Ae(a),maintenance:Se(a),oauth:he(a),tokens:{get:r,set:o,clear:i}}}var k=class extends Error{name="PhoneOtpError"};function O(e,t){return e instanceof k?e:z(e)?new k(e.message||t):e instanceof Error&&e.message?new k(e.message):new k(t)}function Ue(e){if(!z(e)||typeof e.status!="number")return!1;let t=e.status;return t>=400&&t<500&&t!==429}function ze(e){if(e.status!=="in_progress"||!e.debug)return;let t=e.debug.verification_code;return typeof t=="string"?t:void 0}function ft(e){return{...e,id:typeof e.id=="string"?e.id:"",first_name:typeof e.first_name=="string"?e.first_name:typeof e.firstName=="string"?e.firstName:void 0,last_name:typeof e.last_name=="string"?e.last_name:typeof e.lastName=="string"?e.lastName:void 0,email:typeof e.email=="string"?e.email:void 0,phone_number:typeof e.phone_number=="string"?e.phone_number:typeof e.phoneNumber=="string"?e.phoneNumber:void 0,phone_country_code:typeof e.phone_country_code=="string"?e.phone_country_code:typeof e.phoneCountryCode=="string"?e.phoneCountryCode:void 0,phone_verified:typeof e.phone_verified=="boolean"?e.phone_verified:typeof e.phoneVerified=="boolean"?e.phoneVerified:void 0,profile_picture_url:typeof e.profile_picture_url=="string"?e.profile_picture_url:typeof e.profilePictureUrl=="string"?e.profilePictureUrl:void 0,picture:typeof e.picture=="string"?e.picture:void 0,birthdate:typeof e.birthdate=="string"?e.birthdate:void 0}}function lt(e){let t=e.auth,n=e.guestProfile??{firstName:"Guest",lastName:"User"},r=n.emailDomain??"registrations.tktchurch.local",o=n.emailLocalPrefix??"reg";function i(){return t||B({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:q(),autoRefresh:!1})}async function a(p,h){let c=i(),d=await c.flow.initAuthentication({flowType:"phone_only",username:h}),_=await c.flow.executeStep({sessionId:d.sessionId,stepId:d.currentStep.stepId,continuationToken:d.continuationToken,credential:p});if(_.status!=="in_progress")throw new k("Unexpected sign-in response.");return{oauthSessionId:d.sessionId,verifyStepId:_.nextStep.stepId,mode:"authentication",continuationToken:d.continuationToken,debugCode:ze(_)}}async function u(p){let h=i(),c=await h.flow.initRegistration({flowType:"phone_registration"}),d=await h.flow.executeRegistrationStep({sessionId:c.sessionId,stepId:c.currentStep.stepId,continuationToken:c.continuationToken,credential:p});if(d.status!=="in_progress")throw new k("Unexpected verification response.");return{oauthSessionId:c.sessionId,verifyStepId:d.nextStep.stepId,mode:"registration",continuationToken:c.continuationToken,debugCode:ze(d)}}async function f(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await u(d)}catch(_){if(!Ue(_))throw O(_,"Could not send the code. Please try again.");try{return await a(d,c)}catch{throw O(_,"Could not send the code. Please try again.")}}}async function R(p,h,c){let d={phone_country_code:p,phone_number:h};try{return await a(d,c)}catch(_){if(!Ue(_))throw O(_,"Could not start sign-in.");try{return await u(d)}catch{throw O(_,"Could not start sign-in.")}}}async function m(p,h,c,d,_,U){return h==="registration"?await p.flow.executeRegistrationStep({sessionId:c,stepId:d,continuationToken:_,credential:U}):await p.flow.executeStep({sessionId:c,stepId:d,continuationToken:_,credential:U})}async function w(p,h){let c=i();try{let d=await m(c,p.mode,p.oauthSessionId,p.verifyStepId,p.continuationToken,{code:h}),_=0;for(;d.status==="in_progress"&&_<6;){_++;let U=d.nextStep.stepType,J={};U==="profile_info"?J={first_name:n.firstName,last_name:n.lastName,email:`${o}+${p.oauthSessionId.slice(0,8).toLowerCase()}@${r}`}:U==="terms_acceptance"&&(J={accepted:"true"}),d=await m(c,p.mode,p.oauthSessionId,d.nextStep.stepId,p.continuationToken,J)}if(d.status!=="complete")throw new k("Sign-in did not complete. Please try again.");return{accessToken:d.accessToken,refreshToken:d.refreshToken,expiresIn:d.expiresIn}}catch(d){throw d instanceof k?d:O(d,"That code didn't match. Try again.")}}async function I(p){let h;if(t)h=t;else{let c=q();await c.set({accessToken:p,tokenType:"Bearer",expiresIn:3600}),h=B({baseUrl:e.baseUrl,clientId:e.clientId,allowInsecureTransport:e.allowInsecureTransport,timeoutMs:e.timeoutMs??2e4,storage:c,autoRefresh:!1})}try{let c=await h.user.me();return ft(c)}catch(c){throw O(c,c instanceof s?`Profile fetch failed (${c.status??"error"})`:"Profile fetch failed")}}return{startPhoneOTP:f,startPhoneOTPForSignIn:R,verifyPhoneOTP:w,fetchProfile:I}}var mt=/[\u0000-\u001f\u007f-\u009f\u2028\u2029]/;function ht(e,t="/"){if(!e)return t;let n=e;try{n=decodeURIComponent(e)}catch{return t}return n.startsWith("/")&&!n.startsWith("//")&&!n.startsWith("/\\")&&!mt.test(n)&&!/^\/+[\\/]/.test(n)?n:t}export{P as AuthContractError,s as AuthError,G as DEFAULT_AUTHORIZE_SCOPE,ot as DEFAULT_TOKEN_STORAGE_KEY,ne as MAX_STORED_TOKEN_BYTES,T as MFARequiredAuthError,k as PhoneOtpError,x as assertValidAuthTokens,B as createAuthClient,q as createMemoryTokenStorage,lt as createPhoneOtpClient,ce as deriveCodeChallenge,de as generateCodeVerifier,M as generateNonce,$ as generatePkce,j as generateState,z as isAuthError,je as isUnrecoverableAuthError,st as parseStoredAuthTokens,D as randomUrlSafeString,at as safeParseStoredJson,ht as sanitizePostAuthRedirect,dt as serializeAuthTokens,W as timingSafeEqual,ut as validateStorageKey};
@@ -1195,6 +1195,7 @@ interface UserProfile {
1195
1195
  id: string;
1196
1196
  organizationId?: string;
1197
1197
  email?: string;
1198
+ emailVerified?: boolean;
1198
1199
  username?: string;
1199
1200
  firstName?: string;
1200
1201
  lastName?: string;
@@ -1203,6 +1204,20 @@ interface UserProfile {
1203
1204
  mfaEnabled?: boolean;
1204
1205
  [key: string]: JsonValue | undefined;
1205
1206
  }
1207
+ /** Starts primary-email verification without changing the current email. */
1208
+ interface StartEmailVerificationRequest {
1209
+ email: string;
1210
+ }
1211
+ /** Completes the current authenticated user's staged email challenge. */
1212
+ interface VerifyEmailVerificationRequest {
1213
+ code: string;
1214
+ }
1215
+ /** Primary-email verification lifecycle response. */
1216
+ interface EmailVerificationResponse {
1217
+ status: "sent" | "verified";
1218
+ email: string;
1219
+ emailVerified: boolean;
1220
+ }
1206
1221
  /** OIDC UserInfo response payload. */
1207
1222
  interface UserInfoResponse {
1208
1223
  sub: string;
@@ -1292,6 +1307,10 @@ interface AuthorizeEndpoints {
1292
1307
  interface UserEndpoints {
1293
1308
  me(): Promise<UserProfile>;
1294
1309
  updateMe(input: JsonObject): Promise<UserProfile>;
1310
+ emailVerification: {
1311
+ start(input: StartEmailVerificationRequest): Promise<EmailVerificationResponse>;
1312
+ verify(input: VerifyEmailVerificationRequest): Promise<EmailVerificationResponse>;
1313
+ };
1295
1314
  changePassword(input: {
1296
1315
  currentPassword: string;
1297
1316
  newPassword: string;
@@ -1392,4 +1411,4 @@ interface ApiRequestOptions {
1392
1411
  */
1393
1412
  declare function createMemoryTokenStorage(): TokenStorage;
1394
1413
 
1395
- export { type TokenStorage as $, type AuthClientConfig as A, type OidcEndpoints as B, type ConsumerAuthClient as C, type PageResponse as D, type ExecuteStepRequest as E, type FlowEndpoints as F, type PasswordResetEndpoints as G, type HandleCallbackOptions as H, type InitAuthenticationRequest as I, type PasswordTokenRequest as J, type PublicClientInfo as K, type PushAuthorizationRequestOptions as L, type MaintenanceStatus as M, type PushedAuthorizationResult as N, type OAuthAuthorizationServerMetadata as O, type PageQuery as P, type RevocationResponse as Q, type RefreshTokenRequest as R, type RevokeSessionRequest as S, type RevokeTokenRequest as T, type SessionDetail as U, type SessionEndpoints as V, type SessionListQuery as W, type SessionSummary as X, type TokenEndpoints as Y, type TokenExchangeRequest as Z, type TokenIntrospectionResponse as _, type AuthClient as a, type UpdateSessionRequest as a0, type UserEndpoints as a1, type UserInfoResponse as a2, type UserProfile as a3, type WebAuthnEndpoints as a4, createMemoryTokenStorage as a5, type AuthTokens as b, type AuthorizationCodeTokenRequest as c, type AuthorizationConsentBody as d, type AuthorizationConsentResponse as e, type AuthorizationDetail as f, type AuthorizationProbeResult as g, type AuthorizationRequest as h, type AuthorizationUrlOptions as i, type AuthorizeEndpoints as j, type CallbackParams as k, type ClientCredentialsRequest as l, type ConsumerMaintenanceEndpoints as m, type ConsumerUserEndpoints as n, type FlowInitResponse as o, type FlowSessionStatus as p, type FlowStep as q, type FlowStepCompleteResult as r, type FlowStepInProgressResult as s, type FlowStepResult as t, type InitRegistrationRequest as u, type IntrospectTokenRequest as v, type MfaDevice as w, type MfaEndpoints as x, type OAuthMetaEndpoints as y, type OidcDiscoveryDocument as z };
1414
+ export { type TokenExchangeRequest as $, type AuthClientConfig as A, type OidcDiscoveryDocument as B, type ConsumerAuthClient as C, type OidcEndpoints as D, type EmailVerificationResponse as E, type FlowEndpoints as F, type PageResponse as G, type HandleCallbackOptions as H, type InitAuthenticationRequest as I, type PasswordResetEndpoints as J, type PasswordTokenRequest as K, type PublicClientInfo as L, type MaintenanceStatus as M, type PushAuthorizationRequestOptions as N, type OAuthAuthorizationServerMetadata as O, type PageQuery as P, type PushedAuthorizationResult as Q, type RefreshTokenRequest as R, type RevocationResponse as S, type RevokeSessionRequest as T, type RevokeTokenRequest as U, type SessionDetail as V, type SessionEndpoints as W, type SessionListQuery as X, type SessionSummary as Y, type StartEmailVerificationRequest as Z, type TokenEndpoints as _, type AuthClient as a, type TokenIntrospectionResponse as a0, type TokenStorage as a1, type UpdateSessionRequest as a2, type UserEndpoints as a3, type UserInfoResponse as a4, type UserProfile as a5, type VerifyEmailVerificationRequest as a6, type WebAuthnEndpoints as a7, createMemoryTokenStorage as a8, type AuthTokens as b, type AuthorizationCodeTokenRequest as c, type AuthorizationConsentBody as d, type AuthorizationConsentResponse as e, type AuthorizationDetail as f, type AuthorizationProbeResult as g, type AuthorizationRequest as h, type AuthorizationUrlOptions as i, type AuthorizeEndpoints as j, type CallbackParams as k, type ClientCredentialsRequest as l, type ConsumerMaintenanceEndpoints as m, type ConsumerUserEndpoints as n, type ExecuteStepRequest as o, type FlowInitResponse as p, type FlowSessionStatus as q, type FlowStep as r, type FlowStepCompleteResult as s, type FlowStepInProgressResult as t, type FlowStepResult as u, type InitRegistrationRequest as v, type IntrospectTokenRequest as w, type MfaDevice as x, type MfaEndpoints as y, type OAuthMetaEndpoints as z };
@@ -1195,6 +1195,7 @@ interface UserProfile {
1195
1195
  id: string;
1196
1196
  organizationId?: string;
1197
1197
  email?: string;
1198
+ emailVerified?: boolean;
1198
1199
  username?: string;
1199
1200
  firstName?: string;
1200
1201
  lastName?: string;
@@ -1203,6 +1204,20 @@ interface UserProfile {
1203
1204
  mfaEnabled?: boolean;
1204
1205
  [key: string]: JsonValue | undefined;
1205
1206
  }
1207
+ /** Starts primary-email verification without changing the current email. */
1208
+ interface StartEmailVerificationRequest {
1209
+ email: string;
1210
+ }
1211
+ /** Completes the current authenticated user's staged email challenge. */
1212
+ interface VerifyEmailVerificationRequest {
1213
+ code: string;
1214
+ }
1215
+ /** Primary-email verification lifecycle response. */
1216
+ interface EmailVerificationResponse {
1217
+ status: "sent" | "verified";
1218
+ email: string;
1219
+ emailVerified: boolean;
1220
+ }
1206
1221
  /** OIDC UserInfo response payload. */
1207
1222
  interface UserInfoResponse {
1208
1223
  sub: string;
@@ -1292,6 +1307,10 @@ interface AuthorizeEndpoints {
1292
1307
  interface UserEndpoints {
1293
1308
  me(): Promise<UserProfile>;
1294
1309
  updateMe(input: JsonObject): Promise<UserProfile>;
1310
+ emailVerification: {
1311
+ start(input: StartEmailVerificationRequest): Promise<EmailVerificationResponse>;
1312
+ verify(input: VerifyEmailVerificationRequest): Promise<EmailVerificationResponse>;
1313
+ };
1295
1314
  changePassword(input: {
1296
1315
  currentPassword: string;
1297
1316
  newPassword: string;
@@ -1392,4 +1411,4 @@ interface ApiRequestOptions {
1392
1411
  */
1393
1412
  declare function createMemoryTokenStorage(): TokenStorage;
1394
1413
 
1395
- export { type TokenStorage as $, type AuthClientConfig as A, type OidcEndpoints as B, type ConsumerAuthClient as C, type PageResponse as D, type ExecuteStepRequest as E, type FlowEndpoints as F, type PasswordResetEndpoints as G, type HandleCallbackOptions as H, type InitAuthenticationRequest as I, type PasswordTokenRequest as J, type PublicClientInfo as K, type PushAuthorizationRequestOptions as L, type MaintenanceStatus as M, type PushedAuthorizationResult as N, type OAuthAuthorizationServerMetadata as O, type PageQuery as P, type RevocationResponse as Q, type RefreshTokenRequest as R, type RevokeSessionRequest as S, type RevokeTokenRequest as T, type SessionDetail as U, type SessionEndpoints as V, type SessionListQuery as W, type SessionSummary as X, type TokenEndpoints as Y, type TokenExchangeRequest as Z, type TokenIntrospectionResponse as _, type AuthClient as a, type UpdateSessionRequest as a0, type UserEndpoints as a1, type UserInfoResponse as a2, type UserProfile as a3, type WebAuthnEndpoints as a4, createMemoryTokenStorage as a5, type AuthTokens as b, type AuthorizationCodeTokenRequest as c, type AuthorizationConsentBody as d, type AuthorizationConsentResponse as e, type AuthorizationDetail as f, type AuthorizationProbeResult as g, type AuthorizationRequest as h, type AuthorizationUrlOptions as i, type AuthorizeEndpoints as j, type CallbackParams as k, type ClientCredentialsRequest as l, type ConsumerMaintenanceEndpoints as m, type ConsumerUserEndpoints as n, type FlowInitResponse as o, type FlowSessionStatus as p, type FlowStep as q, type FlowStepCompleteResult as r, type FlowStepInProgressResult as s, type FlowStepResult as t, type InitRegistrationRequest as u, type IntrospectTokenRequest as v, type MfaDevice as w, type MfaEndpoints as x, type OAuthMetaEndpoints as y, type OidcDiscoveryDocument as z };
1414
+ export { type TokenExchangeRequest as $, type AuthClientConfig as A, type OidcDiscoveryDocument as B, type ConsumerAuthClient as C, type OidcEndpoints as D, type EmailVerificationResponse as E, type FlowEndpoints as F, type PageResponse as G, type HandleCallbackOptions as H, type InitAuthenticationRequest as I, type PasswordResetEndpoints as J, type PasswordTokenRequest as K, type PublicClientInfo as L, type MaintenanceStatus as M, type PushAuthorizationRequestOptions as N, type OAuthAuthorizationServerMetadata as O, type PageQuery as P, type PushedAuthorizationResult as Q, type RefreshTokenRequest as R, type RevocationResponse as S, type RevokeSessionRequest as T, type RevokeTokenRequest as U, type SessionDetail as V, type SessionEndpoints as W, type SessionListQuery as X, type SessionSummary as Y, type StartEmailVerificationRequest as Z, type TokenEndpoints as _, type AuthClient as a, type TokenIntrospectionResponse as a0, type TokenStorage as a1, type UpdateSessionRequest as a2, type UserEndpoints as a3, type UserInfoResponse as a4, type UserProfile as a5, type VerifyEmailVerificationRequest as a6, type WebAuthnEndpoints as a7, createMemoryTokenStorage as a8, type AuthTokens as b, type AuthorizationCodeTokenRequest as c, type AuthorizationConsentBody as d, type AuthorizationConsentResponse as e, type AuthorizationDetail as f, type AuthorizationProbeResult as g, type AuthorizationRequest as h, type AuthorizationUrlOptions as i, type AuthorizeEndpoints as j, type CallbackParams as k, type ClientCredentialsRequest as l, type ConsumerMaintenanceEndpoints as m, type ConsumerUserEndpoints as n, type ExecuteStepRequest as o, type FlowInitResponse as p, type FlowSessionStatus as q, type FlowStep as r, type FlowStepCompleteResult as s, type FlowStepInProgressResult as t, type FlowStepResult as u, type InitRegistrationRequest as v, type IntrospectTokenRequest as w, type MfaDevice as x, type MfaEndpoints as y, type OAuthMetaEndpoints as z };
@@ -1 +1 @@
1
- export { a5 as createMemoryTokenStorage } from '../memory-CSq_KMM2.cjs';
1
+ export { a8 as createMemoryTokenStorage } from '../memory-DCHtjktX.cjs';
@@ -1 +1 @@
1
- export { a5 as createMemoryTokenStorage } from '../memory-CSq_KMM2.js';
1
+ export { a8 as createMemoryTokenStorage } from '../memory-DCHtjktX.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tktchurch/auth",
3
- "version": "0.9.7",
3
+ "version": "0.9.9",
4
4
  "description": "Framework-agnostic auth SDK for TKTChurch OAuth/AuthFlow services",
5
5
  "license": "MIT",
6
6
  "type": "module",