@vaiftech/auth 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +177 -0
- package/dist/chunk-JF55RF72.mjs +1 -0
- package/dist/client-28ISGmu6.d.mts +611 -0
- package/dist/client-28ISGmu6.d.ts +611 -0
- package/dist/index.d.mts +83 -0
- package/dist/index.d.ts +83 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/react.d.mts +158 -0
- package/dist/react.d.ts +158 -0
- package/dist/react.js +1 -0
- package/dist/react.mjs +1 -0
- package/package.json +71 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { S as StorageAdapter, A as AsyncStorageAdapter, a as Session } from './client-28ISGmu6.js';
|
|
2
|
+
export { z as AuthChangeEvent, E as AuthClientConfig, G as AuthError, F as AuthErrorCode, y as AuthEventType, e as AuthResponse, B as AuthStateChangeCallback, D as AuthSubscription, C as ConfirmEmailChangeOptions, I as InvalidCredentialsError, M as MFAChallenge, w as MFAChallengeOptions, x as MFAChallengeResponse, t as MFAFactor, s as MFAMethod, u as MFASetupResponse, v as MFAVerifyOptions, r as OAuthIdentity, O as OAuthProviderType, q as OAuthResponse, R as ResetPasswordOptions, H as SessionExpiredError, d as SessionInfo, o as SetPasswordOptions, m as SignInAnonymouslyOptions, i as SignInWithMagicLinkOptions, h as SignInWithOAuthOptions, j as SignInWithOTPOptions, g as SignInWithPasswordOptions, l as SignInWithSSOOptions, f as SignUpOptions, T as TokenRefreshResponse, n as UpdatePasswordOptions, p as UpdateUserOptions, U as User, b as UserInfo, V as VaifAuthClient, k as VerifyOTPOptions, c as createAuthClient, J as isMFAChallenge } from './client-28ISGmu6.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @vaiftech/auth - Storage utilities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Check if running in browser environment
|
|
10
|
+
*/
|
|
11
|
+
declare function isBrowser(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* In-memory storage fallback
|
|
14
|
+
*/
|
|
15
|
+
declare class MemoryStorage implements StorageAdapter {
|
|
16
|
+
private storage;
|
|
17
|
+
getItem(key: string): string | null;
|
|
18
|
+
setItem(key: string, value: string): void;
|
|
19
|
+
removeItem(key: string): void;
|
|
20
|
+
clear(): void;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Local storage adapter
|
|
24
|
+
*/
|
|
25
|
+
declare class LocalStorageAdapter implements StorageAdapter {
|
|
26
|
+
getItem(key: string): string | null;
|
|
27
|
+
setItem(key: string, value: string): void;
|
|
28
|
+
removeItem(key: string): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Session storage adapter
|
|
32
|
+
*/
|
|
33
|
+
declare class SessionStorageAdapter implements StorageAdapter {
|
|
34
|
+
getItem(key: string): string | null;
|
|
35
|
+
setItem(key: string, value: string): void;
|
|
36
|
+
removeItem(key: string): void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Cookie storage options
|
|
40
|
+
*/
|
|
41
|
+
interface CookieStorageOptions {
|
|
42
|
+
secure?: boolean;
|
|
43
|
+
sameSite?: 'strict' | 'lax' | 'none';
|
|
44
|
+
path?: string;
|
|
45
|
+
domain?: string;
|
|
46
|
+
maxAge?: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Cookie storage adapter with secure defaults
|
|
50
|
+
*/
|
|
51
|
+
declare class CookieStorageAdapter implements StorageAdapter {
|
|
52
|
+
private options;
|
|
53
|
+
constructor(options?: CookieStorageOptions);
|
|
54
|
+
getItem(key: string): string | null;
|
|
55
|
+
setItem(key: string, value: string): void;
|
|
56
|
+
removeItem(key: string): void;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get default storage adapter
|
|
60
|
+
*/
|
|
61
|
+
declare function getDefaultStorage(): StorageAdapter;
|
|
62
|
+
/**
|
|
63
|
+
* Storage helper with session serialization
|
|
64
|
+
*/
|
|
65
|
+
declare class SessionStorage {
|
|
66
|
+
private adapter;
|
|
67
|
+
private keyPrefix;
|
|
68
|
+
constructor(adapter: StorageAdapter | AsyncStorageAdapter, keyPrefix?: string);
|
|
69
|
+
private key;
|
|
70
|
+
getSession(): Promise<Session | null>;
|
|
71
|
+
setSession(session: Session): Promise<void>;
|
|
72
|
+
removeSession(): Promise<void>;
|
|
73
|
+
getRefreshToken(): Promise<string | null>;
|
|
74
|
+
setRefreshToken(token: string): Promise<void>;
|
|
75
|
+
removeRefreshToken(): Promise<void>;
|
|
76
|
+
clear(): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
declare const memoryStorage: MemoryStorage;
|
|
79
|
+
declare const localStorage: MemoryStorage | LocalStorageAdapter;
|
|
80
|
+
declare const sessionStorage: MemoryStorage | SessionStorageAdapter;
|
|
81
|
+
declare const cookieStorage: (options?: CookieStorageOptions) => CookieStorageAdapter;
|
|
82
|
+
|
|
83
|
+
export { AsyncStorageAdapter, type CookieStorageOptions, Session, SessionStorage, StorageAdapter, cookieStorage, getDefaultStorage, isBrowser, localStorage, memoryStorage, sessionStorage };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';function c(i){return "mfaRequired"in i&&i.mfaRequired===true}var a=class i extends Error{constructor(e,t,s,r){super(e),this.name="AuthError",this.code=t,this.status=s,this.details=r;}static isAuthError(e){return e instanceof i}},g=class extends a{constructor(e="Session has expired"){super(e,"session_expired",401),this.name="SessionExpiredError";}},f=class extends a{constructor(e="Invalid email or password"){super(e,"invalid_credentials",401),this.name="InvalidCredentialsError";}};function n(){return typeof window<"u"&&typeof window.document<"u"}function _(){if(!n())return false;try{let i="__vaif_test__";return window.localStorage.setItem(i,i),window.localStorage.removeItem(i),!0}catch{return false}}var p=class{constructor(){this.storage=new Map;}getItem(e){return this.storage.get(e)??null}setItem(e,t){this.storage.set(e,t);}removeItem(e){this.storage.delete(e);}clear(){this.storage.clear();}},l=class{getItem(e){if(!n())return null;try{return window.localStorage.getItem(e)}catch{return null}}setItem(e,t){if(n())try{window.localStorage.setItem(e,t);}catch{}}removeItem(e){if(n())try{window.localStorage.removeItem(e);}catch{}}},m=class{getItem(e){if(!n())return null;try{return window.sessionStorage.getItem(e)}catch{return null}}setItem(e,t){if(n())try{window.sessionStorage.setItem(e,t);}catch{}}removeItem(e){if(n())try{window.sessionStorage.removeItem(e);}catch{}}},S=class{constructor(e){this.options={secure:n()&&window.location.protocol==="https:",sameSite:"lax",path:"/",...e};}getItem(e){if(!n())return null;try{let t=document.cookie.split(";");for(let s of t){let[r,o]=s.trim().split("=");if(r===e)return decodeURIComponent(o)}return null}catch{return null}}setItem(e,t){if(n())try{let s=`${e}=${encodeURIComponent(t)}`;s+=`; path=${this.options.path}`,s+=`; samesite=${this.options.sameSite}`,this.options.secure&&(s+="; secure"),this.options.domain&&(s+=`; domain=${this.options.domain}`),this.options.maxAge&&(s+=`; max-age=${this.options.maxAge}`),document.cookie=s;}catch{}}removeItem(e){if(n())try{document.cookie=`${e}=; path=${this.options.path}; expires=Thu, 01 Jan 1970 00:00:00 GMT`;}catch{}}};function y(){return _()?new l:new p}var u=class{constructor(e,t="vaif.auth."){this.adapter=e,this.keyPrefix=t;}key(e){return `${this.keyPrefix}${e}`}async getSession(){try{let e=await this.adapter.getItem(this.key("session"));if(!e)return null;let t=JSON.parse(e);return t.expiresAt&&t.expiresAt<Date.now()?(await this.removeSession(),null):t}catch{return null}}async setSession(e){try{await this.adapter.setItem(this.key("session"),JSON.stringify(e));}catch{}}async removeSession(){try{await this.adapter.removeItem(this.key("session"));}catch{}}async getRefreshToken(){try{return await this.adapter.getItem(this.key("refresh_token"))}catch{return null}}async setRefreshToken(e){try{await this.adapter.setItem(this.key("refresh_token"),e);}catch{}}async removeRefreshToken(){try{await this.adapter.removeItem(this.key("refresh_token"));}catch{}}async clear(){await this.removeSession(),await this.removeRefreshToken();}},A=new p,O=_()?new l:A,k=n()?new m:A,v=i=>new S(i);var P={storageKey:"vaif.auth.",autoRefreshToken:true,persistSession:true,detectSessionInUrl:true,flowType:"implicit",debug:false},I=60*1e3,d=class{constructor(e){this.refreshTimer=null;this.listeners=new Set;this.initialized=false;this.initPromise=null;this.currentSession=null;this.config={...P,...e,headers:e.headers||{},storage:e.storage||y()},this.storage=new u(this.config.storage,this.config.storageKey);}async initialize(){return this.initPromise?this.initPromise.then(()=>this.currentSession):(this.initPromise=this._initialize(),await this.initPromise,this.currentSession)}async _initialize(){if(!this.initialized){if(this.config.detectSessionInUrl&&n()){let e=await this._handleUrlSession();if(e){this.currentSession=e,await this._persistSession(e),this._notifyListeners("SIGNED_IN",e),this._setupAutoRefresh(e),this.initialized=true;return}}if(this.config.persistSession){let e=await this.storage.getSession();e&&(this.currentSession=e,this._notifyListeners("INITIAL_SESSION",e),this._setupAutoRefresh(e));}this.initialized=true;}}async getSession(){return await this.initialize(),this.currentSession}async getUser(){return (await this.getSession())?.user??null}async setSession(e,t){let s=await this._fetchUser(e),r={accessToken:e,refreshToken:t,expiresAt:Date.now()+3600*1e3,expiresIn:3600,tokenType:"bearer",user:s};return this.currentSession=r,await this._persistSession(r),this._notifyListeners("SIGNED_IN",r),this._setupAutoRefresh(r),{session:r,user:s}}async refreshSession(){let e=await this.getSession();if(!e?.refreshToken)return null;try{let t=await this._refreshToken(e.refreshToken),s={...e,accessToken:t.accessToken,refreshToken:t.refreshToken||e.refreshToken,expiresAt:t.expiresAt,expiresIn:t.expiresIn};return this.currentSession=s,await this._persistSession(s),this._notifyListeners("TOKEN_REFRESHED",s),this._setupAutoRefresh(s),s}catch(t){return this._log("Failed to refresh session:",t),await this.signOut(),null}}async signUp(e){let t=await this._fetch("/auth/signup",{method:"POST",body:JSON.stringify({email:e.email,password:e.password,name:e.name,phone:e.phone,metadata:e.metadata,redirectUrl:e.redirectUrl||e.emailRedirectTo})});return c(t)||(this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session)),t}async signInWithPassword(e){let t=await this._fetch("/auth/login",{method:"POST",body:JSON.stringify({email:e.email,password:e.password,mfaCode:e.mfaCode,rememberMe:e.rememberMe})});return c(t)||(this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session)),t}async signInWithOAuth(e){let t=await this._fetch("/auth/oauth/authorize",{method:"POST",body:JSON.stringify({provider:e.provider,redirectUrl:e.redirectTo,scopes:e.scopes,queryParams:e.queryParams,flowType:this.config.flowType})});return n()&&(window.location.href=t.url),t}async signInWithMagicLink(e){return this._fetch("/auth/magic-link/send",{method:"POST",body:JSON.stringify({email:e.email,redirectUrl:e.redirectTo,shouldCreateUser:e.shouldCreateUser})})}async signInWithOTP(e){let t=e.phone?"/auth/phone/send":"/auth/otp/send";return this._fetch(t,{method:"POST",body:JSON.stringify({email:e.email,phone:e.phone,channel:e.channel,shouldCreateUser:e.shouldCreateUser})})}async verifyOTP(e){let t=await this._fetch("/auth/otp/verify",{method:"POST",body:JSON.stringify({email:e.email,phone:e.phone,token:e.token,type:e.type})});return this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session),t}async signInAnonymously(e){let t=await this._fetch("/auth/anonymous",{method:"POST",body:JSON.stringify({metadata:e?.metadata})});return this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session),t}async signOut(){try{this.currentSession&&await this._fetch("/auth/logout",{method:"POST"});}catch{}this._clearRefreshTimer(),this.currentSession=null,await this.storage.clear(),this._notifyListeners("SIGNED_OUT",null);}async signOutAll(){try{await this._fetch("/auth/logout-all",{method:"POST"});}catch{}this._clearRefreshTimer(),this.currentSession=null,await this.storage.clear(),this._notifyListeners("SIGNED_OUT",null);}async resetPasswordForEmail(e){return this._fetch("/auth/forgot-password",{method:"POST",body:JSON.stringify({email:e.email,redirectUrl:e.redirectTo})})}async updatePassword(e){return this._fetch("/users/me/change-password",{method:"POST",body:JSON.stringify({currentPassword:e.currentPassword,newPassword:e.newPassword})})}async setPassword(e){let t=await this._fetch("/auth/reset-password",{method:"POST",body:JSON.stringify({token:e.token,password:e.password})});return this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("PASSWORD_RECOVERY",t.session),this._setupAutoRefresh(t.session),t}async updateUser(e){let t=await this._fetch("/users/me",{method:"PATCH",body:JSON.stringify(e)});return this.currentSession&&(this.currentSession={...this.currentSession,user:t.user},await this._persistSession(this.currentSession),this._notifyListeners("USER_UPDATED",this.currentSession)),t.user}async getUserIdentities(){return (await this._fetch("/auth/oauth/providers")).identities}async linkIdentity(e,t){let s=await this._fetch("/auth/oauth/link",{method:"POST",body:JSON.stringify({provider:e,redirectUrl:t?.redirectTo})});return n()&&(window.location.href=s.url),s}async unlinkIdentity(e){return this._fetch(`/auth/oauth/unlink/${e}`,{method:"POST"})}async listMFAFactors(){return (await this._fetch("/auth/mfa/factors")).factors}async enrollMFA(e){return this._fetch("/auth/mfa/setup",{method:"POST",body:JSON.stringify({method:e.type,friendlyName:e.friendlyName})})}async verifyMFA(e){return this._fetch("/auth/mfa/enable",{method:"POST",body:JSON.stringify({factorId:e.factorId,code:e.code})})}async challengeMFA(e){return this._fetch("/auth/mfa/challenge",{method:"POST",body:JSON.stringify({factorId:e.factorId})})}async verifyMFAChallenge(e,t){let s=await this._fetch("/auth/mfa/verify",{method:"POST",body:JSON.stringify({mfaToken:e,code:t})});return this.currentSession=s.session,await this._persistSession(s.session),this._notifyListeners("MFA_CHALLENGE_VERIFIED",s.session),this._setupAutoRefresh(s.session),s}async unenrollMFA(e,t){return this._fetch("/auth/mfa/disable",{method:"POST",body:JSON.stringify({factorId:e,code:t})})}async regenerateBackupCodes(){return this._fetch("/auth/mfa/backup-codes",{method:"POST"})}async listSessions(){return (await this._fetch("/auth/sessions")).sessions}async revokeSession(e){return this._fetch(`/auth/sessions/${e}`,{method:"DELETE"})}async revokeOtherSessions(){return this._fetch("/auth/sessions/revoke-others",{method:"POST"})}async resendEmailVerification(e){return this._fetch("/auth/verify-email/send",{method:"POST",body:JSON.stringify({redirectUrl:e?.redirectTo})})}async verifyEmail(e){let t=await this._fetch("/auth/verify-email/confirm",{method:"POST",body:JSON.stringify({token:e})});return this.currentSession&&(this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("USER_UPDATED",t.session)),t}onAuthStateChange(e){return this.listeners.add(e),this.initialized&&e({event:this.currentSession?"INITIAL_SESSION":"SIGNED_OUT",session:this.currentSession}),{unsubscribe:()=>{this.listeners.delete(e);}}}async _fetch(e,t={}){let s=`${this.config.url}${e}`,r={"Content-Type":"application/json",...this.config.headers};this.config.apiKey&&(r["x-vaif-key"]=this.config.apiKey),this.currentSession?.accessToken&&(r.Authorization=`Bearer ${this.currentSession.accessToken}`);let o=await fetch(s,{...t,headers:r});if(!o.ok){let h=await o.json().catch(()=>({}));throw new a(h.message||"Request failed",this._mapErrorCode(o.status,h.code),o.status,h)}return o.json()}async _fetchUser(e){let t=await fetch(`${this.config.url}/auth/me`,{headers:{Authorization:`Bearer ${e}`,...this.config.headers}});if(!t.ok)throw new a("Failed to fetch user","invalid_token",t.status);return (await t.json()).user}async _refreshToken(e){let t=await fetch(`${this.config.url}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json",...this.config.headers},body:JSON.stringify({refreshToken:e})});if(!t.ok)throw new a("Failed to refresh token","token_expired",t.status);return t.json()}async _handleUrlSession(){if(!n())return null;let e=new URLSearchParams(window.location.hash.substring(1)),t=new URLSearchParams(window.location.search),s=e.get("access_token")||t.get("access_token"),r=e.get("refresh_token")||t.get("refresh_token"),o=e.get("expires_in")||t.get("expires_in");if(!s)return null;try{let h=await this._fetchUser(s),w={accessToken:s,refreshToken:r||void 0,expiresAt:Date.now()+(o?parseInt(o,10)*1e3:36e5),expiresIn:o?parseInt(o,10):3600,tokenType:"bearer",user:h};return window.history.replaceState(null,"",window.location.pathname),w}catch(h){return this._log("Failed to handle URL session:",h),null}}async _persistSession(e){this.config.persistSession&&(await this.storage.setSession(e),e.refreshToken&&await this.storage.setRefreshToken(e.refreshToken));}_setupAutoRefresh(e){if(!this.config.autoRefreshToken||!e.refreshToken)return;this._clearRefreshTimer();let t=e.expiresAt,s=Date.now(),r=Math.max(0,t-s-I);this._log(`Setting up auto refresh in ${Math.round(r/1e3)}s`),this.refreshTimer=setTimeout(()=>{this.refreshSession();},r);}_clearRefreshTimer(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}_notifyListeners(e,t){let s={event:e,session:t};this.listeners.forEach(r=>{try{r(s);}catch(o){this._log("Error in auth state change listener:",o);}});}_mapErrorCode(e,t){if(t){let s={invalid_credentials:"invalid_credentials",user_not_found:"user_not_found",user_already_exists:"user_already_exists",email_not_verified:"email_not_verified",phone_not_verified:"phone_not_verified",invalid_token:"invalid_token",token_expired:"token_expired",mfa_required:"mfa_required",mfa_invalid:"mfa_invalid",rate_limited:"rate_limited",weak_password:"weak_password",invalid_email:"invalid_email",invalid_phone:"invalid_phone"};if(s[t])return s[t]}switch(e){case 401:return "invalid_credentials";case 403:return "token_expired";case 404:return "user_not_found";case 409:return "user_already_exists";case 429:return "rate_limited";default:return "unknown_error"}}_log(...e){this.config.debug&&console.log("[VaifAuth]",...e);}};function T(i){return new d(i)}exports.AuthError=a;exports.InvalidCredentialsError=f;exports.SessionExpiredError=g;exports.SessionStorage=u;exports.VaifAuthClient=d;exports.cookieStorage=v;exports.createAuthClient=T;exports.getDefaultStorage=y;exports.isBrowser=n;exports.isMFAChallenge=c;exports.localStorage=O;exports.memoryStorage=A;exports.sessionStorage=k;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{b as AuthError,d as InvalidCredentialsError,c as SessionExpiredError,g as SessionStorage,l as VaifAuthClient,k as cookieStorage,m as createAuthClient,f as getDefaultStorage,e as isBrowser,a as isMFAChallenge,i as localStorage,h as memoryStorage,j as sessionStorage}from'./chunk-JF55RF72.mjs';
|
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { E as AuthClientConfig, V as VaifAuthClient, a as Session, U as User, f as SignUpOptions, e as AuthResponse, M as MFAChallenge, g as SignInWithPasswordOptions, h as SignInWithOAuthOptions, i as SignInWithMagicLinkOptions, t as MFAFactor, u as MFASetupResponse, r as OAuthIdentity, O as OAuthProviderType, q as OAuthResponse, d as SessionInfo } from './client-28ISGmu6.mjs';
|
|
2
|
+
export { z as AuthChangeEvent, y as AuthEventType, D as AuthSubscription, c as createAuthClient } from './client-28ISGmu6.mjs';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
interface AuthProviderProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Auth client configuration
|
|
10
|
+
*/
|
|
11
|
+
config?: AuthClientConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Pre-configured auth client instance
|
|
14
|
+
*/
|
|
15
|
+
client?: VaifAuthClient;
|
|
16
|
+
/**
|
|
17
|
+
* Initial session (for SSR)
|
|
18
|
+
*/
|
|
19
|
+
initialSession?: Session | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Auth provider component
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* import { AuthProvider } from '@vaiftech/auth/react';
|
|
27
|
+
*
|
|
28
|
+
* function App() {
|
|
29
|
+
* return (
|
|
30
|
+
* <AuthProvider config={{ url: 'https://api.vaif.studio', apiKey: 'your-key' }}>
|
|
31
|
+
* <YourApp />
|
|
32
|
+
* </AuthProvider>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare function AuthProvider({ children, config, client: providedClient, initialSession, }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* Get the auth client instance
|
|
40
|
+
*/
|
|
41
|
+
declare function useAuthClient(): VaifAuthClient;
|
|
42
|
+
/**
|
|
43
|
+
* Main auth hook with all auth state and methods
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* function LoginPage() {
|
|
48
|
+
* const {
|
|
49
|
+
* user,
|
|
50
|
+
* isLoading,
|
|
51
|
+
* isAuthenticated,
|
|
52
|
+
* signInWithPassword,
|
|
53
|
+
* signInWithOAuth,
|
|
54
|
+
* signOut,
|
|
55
|
+
* } = useAuth();
|
|
56
|
+
*
|
|
57
|
+
* if (isLoading) return <Loading />;
|
|
58
|
+
* if (isAuthenticated) return <Redirect to="/dashboard" />;
|
|
59
|
+
*
|
|
60
|
+
* return (
|
|
61
|
+
* <form onSubmit={(e) => {
|
|
62
|
+
* e.preventDefault();
|
|
63
|
+
* signInWithPassword({ email, password });
|
|
64
|
+
* }}>
|
|
65
|
+
* ...
|
|
66
|
+
* </form>
|
|
67
|
+
* );
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function useAuth(): {
|
|
72
|
+
session: Session | null;
|
|
73
|
+
user: User | null;
|
|
74
|
+
isLoading: boolean;
|
|
75
|
+
isAuthenticated: boolean;
|
|
76
|
+
error: Error | null;
|
|
77
|
+
signUp: (options: SignUpOptions) => Promise<AuthResponse | MFAChallenge>;
|
|
78
|
+
signInWithPassword: (options: SignInWithPasswordOptions) => Promise<AuthResponse | MFAChallenge>;
|
|
79
|
+
signInWithOAuth: (options: SignInWithOAuthOptions) => Promise<void>;
|
|
80
|
+
signInWithMagicLink: (options: SignInWithMagicLinkOptions) => Promise<{
|
|
81
|
+
ok: boolean;
|
|
82
|
+
}>;
|
|
83
|
+
signOut: () => Promise<void>;
|
|
84
|
+
refreshSession: () => Promise<Session | null>;
|
|
85
|
+
client: VaifAuthClient;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Get the current user
|
|
89
|
+
*/
|
|
90
|
+
declare function useUser(): User | null;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current session
|
|
93
|
+
*/
|
|
94
|
+
declare function useSession(): Session | null;
|
|
95
|
+
/**
|
|
96
|
+
* Check if user is authenticated
|
|
97
|
+
*/
|
|
98
|
+
declare function useIsAuthenticated(): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Password management hook
|
|
101
|
+
*/
|
|
102
|
+
declare function usePassword(): {
|
|
103
|
+
resetPassword: (email: string, redirectTo?: string) => Promise<{
|
|
104
|
+
ok: boolean;
|
|
105
|
+
}>;
|
|
106
|
+
updatePassword: (currentPassword: string, newPassword: string) => Promise<{
|
|
107
|
+
ok: boolean;
|
|
108
|
+
}>;
|
|
109
|
+
isLoading: boolean;
|
|
110
|
+
error: Error | null;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* MFA management hook
|
|
114
|
+
*/
|
|
115
|
+
declare function useMFA(): {
|
|
116
|
+
factors: MFAFactor[];
|
|
117
|
+
isLoading: boolean;
|
|
118
|
+
error: Error | null;
|
|
119
|
+
enrollTOTP: (friendlyName?: string) => Promise<MFASetupResponse>;
|
|
120
|
+
verifyMFA: (factorId: string, code: string) => Promise<{
|
|
121
|
+
ok: boolean;
|
|
122
|
+
backupCodes?: string[];
|
|
123
|
+
}>;
|
|
124
|
+
unenroll: (factorId: string, code: string) => Promise<{
|
|
125
|
+
ok: boolean;
|
|
126
|
+
}>;
|
|
127
|
+
refresh: () => Promise<void>;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* OAuth identities management hook
|
|
131
|
+
*/
|
|
132
|
+
declare function useIdentities(): {
|
|
133
|
+
identities: OAuthIdentity[];
|
|
134
|
+
isLoading: boolean;
|
|
135
|
+
error: Error | null;
|
|
136
|
+
linkIdentity: (provider: OAuthProviderType, redirectTo?: string) => Promise<OAuthResponse>;
|
|
137
|
+
unlinkIdentity: (provider: OAuthProviderType) => Promise<{
|
|
138
|
+
ok: boolean;
|
|
139
|
+
}>;
|
|
140
|
+
refresh: () => Promise<void>;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Sessions management hook
|
|
144
|
+
*/
|
|
145
|
+
declare function useSessions(): {
|
|
146
|
+
sessions: SessionInfo[];
|
|
147
|
+
isLoading: boolean;
|
|
148
|
+
error: Error | null;
|
|
149
|
+
revokeSession: (sessionId: string) => Promise<{
|
|
150
|
+
ok: boolean;
|
|
151
|
+
}>;
|
|
152
|
+
revokeOtherSessions: () => Promise<{
|
|
153
|
+
ok: boolean;
|
|
154
|
+
}>;
|
|
155
|
+
refresh: () => Promise<void>;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export { AuthClientConfig, AuthProvider, type AuthProviderProps, AuthResponse, MFAChallenge, MFAFactor, Session, User, VaifAuthClient, useAuth, useAuthClient, useIdentities, useIsAuthenticated, useMFA, usePassword, useSession, useSessions, useUser };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { E as AuthClientConfig, V as VaifAuthClient, a as Session, U as User, f as SignUpOptions, e as AuthResponse, M as MFAChallenge, g as SignInWithPasswordOptions, h as SignInWithOAuthOptions, i as SignInWithMagicLinkOptions, t as MFAFactor, u as MFASetupResponse, r as OAuthIdentity, O as OAuthProviderType, q as OAuthResponse, d as SessionInfo } from './client-28ISGmu6.js';
|
|
2
|
+
export { z as AuthChangeEvent, y as AuthEventType, D as AuthSubscription, c as createAuthClient } from './client-28ISGmu6.js';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
interface AuthProviderProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Auth client configuration
|
|
10
|
+
*/
|
|
11
|
+
config?: AuthClientConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Pre-configured auth client instance
|
|
14
|
+
*/
|
|
15
|
+
client?: VaifAuthClient;
|
|
16
|
+
/**
|
|
17
|
+
* Initial session (for SSR)
|
|
18
|
+
*/
|
|
19
|
+
initialSession?: Session | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Auth provider component
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```tsx
|
|
26
|
+
* import { AuthProvider } from '@vaiftech/auth/react';
|
|
27
|
+
*
|
|
28
|
+
* function App() {
|
|
29
|
+
* return (
|
|
30
|
+
* <AuthProvider config={{ url: 'https://api.vaif.studio', apiKey: 'your-key' }}>
|
|
31
|
+
* <YourApp />
|
|
32
|
+
* </AuthProvider>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare function AuthProvider({ children, config, client: providedClient, initialSession, }: AuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* Get the auth client instance
|
|
40
|
+
*/
|
|
41
|
+
declare function useAuthClient(): VaifAuthClient;
|
|
42
|
+
/**
|
|
43
|
+
* Main auth hook with all auth state and methods
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* function LoginPage() {
|
|
48
|
+
* const {
|
|
49
|
+
* user,
|
|
50
|
+
* isLoading,
|
|
51
|
+
* isAuthenticated,
|
|
52
|
+
* signInWithPassword,
|
|
53
|
+
* signInWithOAuth,
|
|
54
|
+
* signOut,
|
|
55
|
+
* } = useAuth();
|
|
56
|
+
*
|
|
57
|
+
* if (isLoading) return <Loading />;
|
|
58
|
+
* if (isAuthenticated) return <Redirect to="/dashboard" />;
|
|
59
|
+
*
|
|
60
|
+
* return (
|
|
61
|
+
* <form onSubmit={(e) => {
|
|
62
|
+
* e.preventDefault();
|
|
63
|
+
* signInWithPassword({ email, password });
|
|
64
|
+
* }}>
|
|
65
|
+
* ...
|
|
66
|
+
* </form>
|
|
67
|
+
* );
|
|
68
|
+
* }
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
declare function useAuth(): {
|
|
72
|
+
session: Session | null;
|
|
73
|
+
user: User | null;
|
|
74
|
+
isLoading: boolean;
|
|
75
|
+
isAuthenticated: boolean;
|
|
76
|
+
error: Error | null;
|
|
77
|
+
signUp: (options: SignUpOptions) => Promise<AuthResponse | MFAChallenge>;
|
|
78
|
+
signInWithPassword: (options: SignInWithPasswordOptions) => Promise<AuthResponse | MFAChallenge>;
|
|
79
|
+
signInWithOAuth: (options: SignInWithOAuthOptions) => Promise<void>;
|
|
80
|
+
signInWithMagicLink: (options: SignInWithMagicLinkOptions) => Promise<{
|
|
81
|
+
ok: boolean;
|
|
82
|
+
}>;
|
|
83
|
+
signOut: () => Promise<void>;
|
|
84
|
+
refreshSession: () => Promise<Session | null>;
|
|
85
|
+
client: VaifAuthClient;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Get the current user
|
|
89
|
+
*/
|
|
90
|
+
declare function useUser(): User | null;
|
|
91
|
+
/**
|
|
92
|
+
* Get the current session
|
|
93
|
+
*/
|
|
94
|
+
declare function useSession(): Session | null;
|
|
95
|
+
/**
|
|
96
|
+
* Check if user is authenticated
|
|
97
|
+
*/
|
|
98
|
+
declare function useIsAuthenticated(): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Password management hook
|
|
101
|
+
*/
|
|
102
|
+
declare function usePassword(): {
|
|
103
|
+
resetPassword: (email: string, redirectTo?: string) => Promise<{
|
|
104
|
+
ok: boolean;
|
|
105
|
+
}>;
|
|
106
|
+
updatePassword: (currentPassword: string, newPassword: string) => Promise<{
|
|
107
|
+
ok: boolean;
|
|
108
|
+
}>;
|
|
109
|
+
isLoading: boolean;
|
|
110
|
+
error: Error | null;
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* MFA management hook
|
|
114
|
+
*/
|
|
115
|
+
declare function useMFA(): {
|
|
116
|
+
factors: MFAFactor[];
|
|
117
|
+
isLoading: boolean;
|
|
118
|
+
error: Error | null;
|
|
119
|
+
enrollTOTP: (friendlyName?: string) => Promise<MFASetupResponse>;
|
|
120
|
+
verifyMFA: (factorId: string, code: string) => Promise<{
|
|
121
|
+
ok: boolean;
|
|
122
|
+
backupCodes?: string[];
|
|
123
|
+
}>;
|
|
124
|
+
unenroll: (factorId: string, code: string) => Promise<{
|
|
125
|
+
ok: boolean;
|
|
126
|
+
}>;
|
|
127
|
+
refresh: () => Promise<void>;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* OAuth identities management hook
|
|
131
|
+
*/
|
|
132
|
+
declare function useIdentities(): {
|
|
133
|
+
identities: OAuthIdentity[];
|
|
134
|
+
isLoading: boolean;
|
|
135
|
+
error: Error | null;
|
|
136
|
+
linkIdentity: (provider: OAuthProviderType, redirectTo?: string) => Promise<OAuthResponse>;
|
|
137
|
+
unlinkIdentity: (provider: OAuthProviderType) => Promise<{
|
|
138
|
+
ok: boolean;
|
|
139
|
+
}>;
|
|
140
|
+
refresh: () => Promise<void>;
|
|
141
|
+
};
|
|
142
|
+
/**
|
|
143
|
+
* Sessions management hook
|
|
144
|
+
*/
|
|
145
|
+
declare function useSessions(): {
|
|
146
|
+
sessions: SessionInfo[];
|
|
147
|
+
isLoading: boolean;
|
|
148
|
+
error: Error | null;
|
|
149
|
+
revokeSession: (sessionId: string) => Promise<{
|
|
150
|
+
ok: boolean;
|
|
151
|
+
}>;
|
|
152
|
+
revokeOtherSessions: () => Promise<{
|
|
153
|
+
ok: boolean;
|
|
154
|
+
}>;
|
|
155
|
+
refresh: () => Promise<void>;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export { AuthClientConfig, AuthProvider, type AuthProviderProps, AuthResponse, MFAChallenge, MFAFactor, Session, User, VaifAuthClient, useAuth, useAuthClient, useIdentities, useIsAuthenticated, useMFA, usePassword, useSession, useSessions, useUser };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var react=require('react'),jsxRuntime=require('react/jsx-runtime');function I(s){return "mfaRequired"in s&&s.mfaRequired===true}var m=class s extends Error{constructor(e,t,r,n){super(e),this.name="AuthError",this.code=t,this.status=r,this.details=n;}static isAuthError(e){return e instanceof s}};function f(){return typeof window<"u"&&typeof window.document<"u"}function C(){if(!f())return false;try{let s="__vaif_test__";return window.localStorage.setItem(s,s),window.localStorage.removeItem(s),!0}catch{return false}}var w=class{constructor(){this.storage=new Map;}getItem(e){return this.storage.get(e)??null}setItem(e,t){this.storage.set(e,t);}removeItem(e){this.storage.delete(e);}clear(){this.storage.clear();}},_=class{getItem(e){if(!f())return null;try{return window.localStorage.getItem(e)}catch{return null}}setItem(e,t){if(f())try{window.localStorage.setItem(e,t);}catch{}}removeItem(e){if(f())try{window.localStorage.removeItem(e);}catch{}}};function R(){return C()?new _:new w}var v=class{constructor(e,t="vaif.auth."){this.adapter=e,this.keyPrefix=t;}key(e){return `${this.keyPrefix}${e}`}async getSession(){try{let e=await this.adapter.getItem(this.key("session"));if(!e)return null;let t=JSON.parse(e);return t.expiresAt&&t.expiresAt<Date.now()?(await this.removeSession(),null):t}catch{return null}}async setSession(e){try{await this.adapter.setItem(this.key("session"),JSON.stringify(e));}catch{}}async removeSession(){try{await this.adapter.removeItem(this.key("session"));}catch{}}async getRefreshToken(){try{return await this.adapter.getItem(this.key("refresh_token"))}catch{return null}}async setRefreshToken(e){try{await this.adapter.setItem(this.key("refresh_token"),e);}catch{}}async removeRefreshToken(){try{await this.adapter.removeItem(this.key("refresh_token"));}catch{}}async clear(){await this.removeSession(),await this.removeRefreshToken();}},b=new w;C()?new _:b;var U={storageKey:"vaif.auth.",autoRefreshToken:true,persistSession:true,detectSessionInUrl:true,flowType:"implicit",debug:false},F=60*1e3,P=class{constructor(e){this.refreshTimer=null;this.listeners=new Set;this.initialized=false;this.initPromise=null;this.currentSession=null;this.config={...U,...e,headers:e.headers||{},storage:e.storage||R()},this.storage=new v(this.config.storage,this.config.storageKey);}async initialize(){return this.initPromise?this.initPromise.then(()=>this.currentSession):(this.initPromise=this._initialize(),await this.initPromise,this.currentSession)}async _initialize(){if(!this.initialized){if(this.config.detectSessionInUrl&&f()){let e=await this._handleUrlSession();if(e){this.currentSession=e,await this._persistSession(e),this._notifyListeners("SIGNED_IN",e),this._setupAutoRefresh(e),this.initialized=true;return}}if(this.config.persistSession){let e=await this.storage.getSession();e&&(this.currentSession=e,this._notifyListeners("INITIAL_SESSION",e),this._setupAutoRefresh(e));}this.initialized=true;}}async getSession(){return await this.initialize(),this.currentSession}async getUser(){return (await this.getSession())?.user??null}async setSession(e,t){let r=await this._fetchUser(e),n={accessToken:e,refreshToken:t,expiresAt:Date.now()+3600*1e3,expiresIn:3600,tokenType:"bearer",user:r};return this.currentSession=n,await this._persistSession(n),this._notifyListeners("SIGNED_IN",n),this._setupAutoRefresh(n),{session:n,user:r}}async refreshSession(){let e=await this.getSession();if(!e?.refreshToken)return null;try{let t=await this._refreshToken(e.refreshToken),r={...e,accessToken:t.accessToken,refreshToken:t.refreshToken||e.refreshToken,expiresAt:t.expiresAt,expiresIn:t.expiresIn};return this.currentSession=r,await this._persistSession(r),this._notifyListeners("TOKEN_REFRESHED",r),this._setupAutoRefresh(r),r}catch(t){return this._log("Failed to refresh session:",t),await this.signOut(),null}}async signUp(e){let t=await this._fetch("/auth/signup",{method:"POST",body:JSON.stringify({email:e.email,password:e.password,name:e.name,phone:e.phone,metadata:e.metadata,redirectUrl:e.redirectUrl||e.emailRedirectTo})});return I(t)||(this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session)),t}async signInWithPassword(e){let t=await this._fetch("/auth/login",{method:"POST",body:JSON.stringify({email:e.email,password:e.password,mfaCode:e.mfaCode,rememberMe:e.rememberMe})});return I(t)||(this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session)),t}async signInWithOAuth(e){let t=await this._fetch("/auth/oauth/authorize",{method:"POST",body:JSON.stringify({provider:e.provider,redirectUrl:e.redirectTo,scopes:e.scopes,queryParams:e.queryParams,flowType:this.config.flowType})});return f()&&(window.location.href=t.url),t}async signInWithMagicLink(e){return this._fetch("/auth/magic-link/send",{method:"POST",body:JSON.stringify({email:e.email,redirectUrl:e.redirectTo,shouldCreateUser:e.shouldCreateUser})})}async signInWithOTP(e){let t=e.phone?"/auth/phone/send":"/auth/otp/send";return this._fetch(t,{method:"POST",body:JSON.stringify({email:e.email,phone:e.phone,channel:e.channel,shouldCreateUser:e.shouldCreateUser})})}async verifyOTP(e){let t=await this._fetch("/auth/otp/verify",{method:"POST",body:JSON.stringify({email:e.email,phone:e.phone,token:e.token,type:e.type})});return this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session),t}async signInAnonymously(e){let t=await this._fetch("/auth/anonymous",{method:"POST",body:JSON.stringify({metadata:e?.metadata})});return this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("SIGNED_IN",t.session),this._setupAutoRefresh(t.session),t}async signOut(){try{this.currentSession&&await this._fetch("/auth/logout",{method:"POST"});}catch{}this._clearRefreshTimer(),this.currentSession=null,await this.storage.clear(),this._notifyListeners("SIGNED_OUT",null);}async signOutAll(){try{await this._fetch("/auth/logout-all",{method:"POST"});}catch{}this._clearRefreshTimer(),this.currentSession=null,await this.storage.clear(),this._notifyListeners("SIGNED_OUT",null);}async resetPasswordForEmail(e){return this._fetch("/auth/forgot-password",{method:"POST",body:JSON.stringify({email:e.email,redirectUrl:e.redirectTo})})}async updatePassword(e){return this._fetch("/users/me/change-password",{method:"POST",body:JSON.stringify({currentPassword:e.currentPassword,newPassword:e.newPassword})})}async setPassword(e){let t=await this._fetch("/auth/reset-password",{method:"POST",body:JSON.stringify({token:e.token,password:e.password})});return this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("PASSWORD_RECOVERY",t.session),this._setupAutoRefresh(t.session),t}async updateUser(e){let t=await this._fetch("/users/me",{method:"PATCH",body:JSON.stringify(e)});return this.currentSession&&(this.currentSession={...this.currentSession,user:t.user},await this._persistSession(this.currentSession),this._notifyListeners("USER_UPDATED",this.currentSession)),t.user}async getUserIdentities(){return (await this._fetch("/auth/oauth/providers")).identities}async linkIdentity(e,t){let r=await this._fetch("/auth/oauth/link",{method:"POST",body:JSON.stringify({provider:e,redirectUrl:t?.redirectTo})});return f()&&(window.location.href=r.url),r}async unlinkIdentity(e){return this._fetch(`/auth/oauth/unlink/${e}`,{method:"POST"})}async listMFAFactors(){return (await this._fetch("/auth/mfa/factors")).factors}async enrollMFA(e){return this._fetch("/auth/mfa/setup",{method:"POST",body:JSON.stringify({method:e.type,friendlyName:e.friendlyName})})}async verifyMFA(e){return this._fetch("/auth/mfa/enable",{method:"POST",body:JSON.stringify({factorId:e.factorId,code:e.code})})}async challengeMFA(e){return this._fetch("/auth/mfa/challenge",{method:"POST",body:JSON.stringify({factorId:e.factorId})})}async verifyMFAChallenge(e,t){let r=await this._fetch("/auth/mfa/verify",{method:"POST",body:JSON.stringify({mfaToken:e,code:t})});return this.currentSession=r.session,await this._persistSession(r.session),this._notifyListeners("MFA_CHALLENGE_VERIFIED",r.session),this._setupAutoRefresh(r.session),r}async unenrollMFA(e,t){return this._fetch("/auth/mfa/disable",{method:"POST",body:JSON.stringify({factorId:e,code:t})})}async regenerateBackupCodes(){return this._fetch("/auth/mfa/backup-codes",{method:"POST"})}async listSessions(){return (await this._fetch("/auth/sessions")).sessions}async revokeSession(e){return this._fetch(`/auth/sessions/${e}`,{method:"DELETE"})}async revokeOtherSessions(){return this._fetch("/auth/sessions/revoke-others",{method:"POST"})}async resendEmailVerification(e){return this._fetch("/auth/verify-email/send",{method:"POST",body:JSON.stringify({redirectUrl:e?.redirectTo})})}async verifyEmail(e){let t=await this._fetch("/auth/verify-email/confirm",{method:"POST",body:JSON.stringify({token:e})});return this.currentSession&&(this.currentSession=t.session,await this._persistSession(t.session),this._notifyListeners("USER_UPDATED",t.session)),t}onAuthStateChange(e){return this.listeners.add(e),this.initialized&&e({event:this.currentSession?"INITIAL_SESSION":"SIGNED_OUT",session:this.currentSession}),{unsubscribe:()=>{this.listeners.delete(e);}}}async _fetch(e,t={}){let r=`${this.config.url}${e}`,n={"Content-Type":"application/json",...this.config.headers};this.config.apiKey&&(n["x-vaif-key"]=this.config.apiKey),this.currentSession?.accessToken&&(n.Authorization=`Bearer ${this.currentSession.accessToken}`);let o=await fetch(r,{...t,headers:n});if(!o.ok){let h=await o.json().catch(()=>({}));throw new m(h.message||"Request failed",this._mapErrorCode(o.status,h.code),o.status,h)}return o.json()}async _fetchUser(e){let t=await fetch(`${this.config.url}/auth/me`,{headers:{Authorization:`Bearer ${e}`,...this.config.headers}});if(!t.ok)throw new m("Failed to fetch user","invalid_token",t.status);return (await t.json()).user}async _refreshToken(e){let t=await fetch(`${this.config.url}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json",...this.config.headers},body:JSON.stringify({refreshToken:e})});if(!t.ok)throw new m("Failed to refresh token","token_expired",t.status);return t.json()}async _handleUrlSession(){if(!f())return null;let e=new URLSearchParams(window.location.hash.substring(1)),t=new URLSearchParams(window.location.search),r=e.get("access_token")||t.get("access_token"),n=e.get("refresh_token")||t.get("refresh_token"),o=e.get("expires_in")||t.get("expires_in");if(!r)return null;try{let h=await this._fetchUser(r),i={accessToken:r,refreshToken:n||void 0,expiresAt:Date.now()+(o?parseInt(o,10)*1e3:36e5),expiresIn:o?parseInt(o,10):3600,tokenType:"bearer",user:h};return window.history.replaceState(null,"",window.location.pathname),i}catch(h){return this._log("Failed to handle URL session:",h),null}}async _persistSession(e){this.config.persistSession&&(await this.storage.setSession(e),e.refreshToken&&await this.storage.setRefreshToken(e.refreshToken));}_setupAutoRefresh(e){if(!this.config.autoRefreshToken||!e.refreshToken)return;this._clearRefreshTimer();let t=e.expiresAt,r=Date.now(),n=Math.max(0,t-r-F);this._log(`Setting up auto refresh in ${Math.round(n/1e3)}s`),this.refreshTimer=setTimeout(()=>{this.refreshSession();},n);}_clearRefreshTimer(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null);}_notifyListeners(e,t){let r={event:e,session:t};this.listeners.forEach(n=>{try{n(r);}catch(o){this._log("Error in auth state change listener:",o);}});}_mapErrorCode(e,t){if(t){let r={invalid_credentials:"invalid_credentials",user_not_found:"user_not_found",user_already_exists:"user_already_exists",email_not_verified:"email_not_verified",phone_not_verified:"phone_not_verified",invalid_token:"invalid_token",token_expired:"token_expired",mfa_required:"mfa_required",mfa_invalid:"mfa_invalid",rate_limited:"rate_limited",weak_password:"weak_password",invalid_email:"invalid_email",invalid_phone:"invalid_phone"};if(r[t])return r[t]}switch(e){case 401:return "invalid_credentials";case 403:return "token_expired";case 404:return "user_not_found";case 409:return "user_already_exists";case 429:return "rate_limited";default:return "unknown_error"}}_log(...e){this.config.debug&&console.log("[VaifAuth]",...e);}};function x(s){return new P(s)}var E=react.createContext(null);function B({children:s,config:e,client:t,initialSession:r=null}){let[n]=react.useState(()=>{if(t)return t;if(!e)throw new Error("AuthProvider requires either config or client prop");return x(e)}),[o,h]=react.useState(r),[i,g]=react.useState(!r),[c,a]=react.useState(null);react.useEffect(()=>{let d=true;n.initialize().then(S=>{d&&(h(S),g(false));}).catch(S=>{d&&(a(S),g(false));});let{unsubscribe:y}=n.onAuthStateChange(S=>{d&&(h(S.session),a(null));});return ()=>{d=false,y();}},[n]);let u=react.useMemo(()=>({client:n,session:o,user:o?.user??null,isLoading:i,isAuthenticated:!!o,error:c}),[n,o,i,c]);return jsxRuntime.jsx(E.Provider,{value:u,children:s})}function A(){let s=react.useContext(E);if(!s)throw new Error("useAuth must be used within an AuthProvider");return s}function O(){let{client:s}=A();return s}function Y(){let{client:s,session:e,user:t,isLoading:r,isAuthenticated:n,error:o}=A(),h=react.useCallback(async d=>s.signUp(d),[s]),i=react.useCallback(async d=>s.signInWithPassword(d),[s]),g=react.useCallback(async d=>{await s.signInWithOAuth(d);},[s]),c=react.useCallback(async d=>s.signInWithMagicLink(d),[s]),a=react.useCallback(async()=>s.signOut(),[s]),u=react.useCallback(async()=>s.refreshSession(),[s]);return {session:e,user:t,isLoading:r,isAuthenticated:n,error:o,signUp:h,signInWithPassword:i,signInWithOAuth:g,signInWithMagicLink:c,signOut:a,refreshSession:u,client:s}}function Q(){let{user:s}=A();return s}function X(){let{session:s}=A();return s}function Z(){let{isAuthenticated:s}=A();return s}function ee(){let s=O(),[e,t]=react.useState(false),[r,n]=react.useState(null),o=react.useCallback(async(i,g)=>{t(true),n(null);try{return await s.resetPasswordForEmail({email:i,redirectTo:g})}catch(c){throw n(c),c}finally{t(false);}},[s]),h=react.useCallback(async(i,g)=>{t(true),n(null);try{return await s.updatePassword({currentPassword:i,newPassword:g})}catch(c){throw n(c),c}finally{t(false);}},[s]);return {resetPassword:o,updatePassword:h,isLoading:e,error:r}}function te(){let s=O(),[e,t]=react.useState([]),[r,n]=react.useState(false),[o,h]=react.useState(null),i=react.useCallback(async()=>{n(true);try{let u=await s.listMFAFactors();t(u);}catch(u){h(u);}finally{n(false);}},[s]),g=react.useCallback(async u=>s.enrollMFA({type:"totp",friendlyName:u}),[s]),c=react.useCallback(async(u,d)=>{let y=await s.verifyMFA({factorId:u,code:d});return await i(),y},[s,i]),a=react.useCallback(async(u,d)=>{let y=await s.unenrollMFA(u,d);return await i(),y},[s,i]);return react.useEffect(()=>{i();},[i]),{factors:e,isLoading:r,error:o,enrollTOTP:g,verifyMFA:c,unenroll:a,refresh:i}}function se(){let s=O(),[e,t]=react.useState([]),[r,n]=react.useState(true),[o,h]=react.useState(null),i=react.useCallback(async()=>{n(true);try{let a=await s.getUserIdentities();t(a);}catch(a){h(a);}finally{n(false);}},[s]),g=react.useCallback(async(a,u)=>s.linkIdentity(a,{redirectTo:u}),[s]),c=react.useCallback(async a=>{let u=await s.unlinkIdentity(a);return await i(),u},[s,i]);return react.useEffect(()=>{i();},[i]),{identities:e,isLoading:r,error:o,linkIdentity:g,unlinkIdentity:c,refresh:i}}function re(){let s=O(),[e,t]=react.useState([]),[r,n]=react.useState(true),[o,h]=react.useState(null),i=react.useCallback(async()=>{n(true);try{let a=await s.listSessions();t(a);}catch(a){h(a);}finally{n(false);}},[s]),g=react.useCallback(async a=>{let u=await s.revokeSession(a);return await i(),u},[s,i]),c=react.useCallback(async()=>{let a=await s.revokeOtherSessions();return await i(),a},[s,i]);return react.useEffect(()=>{i();},[i]),{sessions:e,isLoading:r,error:o,revokeSession:g,revokeOtherSessions:c,refresh:i}}exports.AuthProvider=B;exports.VaifAuthClient=P;exports.createAuthClient=x;exports.useAuth=Y;exports.useAuthClient=O;exports.useIdentities=se;exports.useIsAuthenticated=Z;exports.useMFA=te;exports.usePassword=ee;exports.useSession=X;exports.useSessions=re;exports.useUser=Q;
|
package/dist/react.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {m}from'./chunk-JF55RF72.mjs';export{l as VaifAuthClient,m as createAuthClient}from'./chunk-JF55RF72.mjs';import {createContext,useState,useEffect,useMemo,useCallback,useContext}from'react';import {jsx}from'react/jsx-runtime';var P=createContext(null);function k({children:t,config:A,client:a,initialSession:f=null}){let[s]=useState(()=>{if(a)return a;if(!A)throw new Error("AuthProvider requires either config or client prop");return m(A)}),[c,d]=useState(f),[e,h]=useState(!f),[o,n]=useState(null);useEffect(()=>{let u=true;s.initialize().then(p=>{u&&(d(p),h(false));}).catch(p=>{u&&(n(p),h(false));});let{unsubscribe:g}=s.onAuthStateChange(p=>{u&&(d(p.session),n(null));});return ()=>{u=false,g();}},[s]);let r=useMemo(()=>({client:s,session:c,user:c?.user??null,isLoading:e,isAuthenticated:!!c,error:o}),[s,c,e,o]);return jsx(P.Provider,{value:r,children:t})}function y(){let t=useContext(P);if(!t)throw new Error("useAuth must be used within an AuthProvider");return t}function S(){let{client:t}=y();return t}function L(){let{client:t,session:A,user:a,isLoading:f,isAuthenticated:s,error:c}=y(),d=useCallback(async u=>t.signUp(u),[t]),e=useCallback(async u=>t.signInWithPassword(u),[t]),h=useCallback(async u=>{await t.signInWithOAuth(u);},[t]),o=useCallback(async u=>t.signInWithMagicLink(u),[t]),n=useCallback(async()=>t.signOut(),[t]),r=useCallback(async()=>t.refreshSession(),[t]);return {session:A,user:a,isLoading:f,isAuthenticated:s,error:c,signUp:d,signInWithPassword:e,signInWithOAuth:h,signInWithMagicLink:o,signOut:n,refreshSession:r,client:t}}function b(){let{user:t}=y();return t}function W(){let{session:t}=y();return t}function U(){let{isAuthenticated:t}=y();return t}function T(){let t=S(),[A,a]=useState(false),[f,s]=useState(null),c=useCallback(async(e,h)=>{a(true),s(null);try{return await t.resetPasswordForEmail({email:e,redirectTo:h})}catch(o){throw s(o),o}finally{a(false);}},[t]),d=useCallback(async(e,h)=>{a(true),s(null);try{return await t.updatePassword({currentPassword:e,newPassword:h})}catch(o){throw s(o),o}finally{a(false);}},[t]);return {resetPassword:c,updatePassword:d,isLoading:A,error:f}}function R(){let t=S(),[A,a]=useState([]),[f,s]=useState(false),[c,d]=useState(null),e=useCallback(async()=>{s(true);try{let r=await t.listMFAFactors();a(r);}catch(r){d(r);}finally{s(false);}},[t]),h=useCallback(async r=>t.enrollMFA({type:"totp",friendlyName:r}),[t]),o=useCallback(async(r,u)=>{let g=await t.verifyMFA({factorId:r,code:u});return await e(),g},[t,e]),n=useCallback(async(r,u)=>{let g=await t.unenrollMFA(r,u);return await e(),g},[t,e]);return useEffect(()=>{e();},[e]),{factors:A,isLoading:f,error:c,enrollTOTP:h,verifyMFA:o,unenroll:n,refresh:e}}function V(){let t=S(),[A,a]=useState([]),[f,s]=useState(true),[c,d]=useState(null),e=useCallback(async()=>{s(true);try{let n=await t.getUserIdentities();a(n);}catch(n){d(n);}finally{s(false);}},[t]),h=useCallback(async(n,r)=>t.linkIdentity(n,{redirectTo:r}),[t]),o=useCallback(async n=>{let r=await t.unlinkIdentity(n);return await e(),r},[t,e]);return useEffect(()=>{e();},[e]),{identities:A,isLoading:f,error:c,linkIdentity:h,unlinkIdentity:o,refresh:e}}function N(){let t=S(),[A,a]=useState([]),[f,s]=useState(true),[c,d]=useState(null),e=useCallback(async()=>{s(true);try{let n=await t.listSessions();a(n);}catch(n){d(n);}finally{s(false);}},[t]),h=useCallback(async n=>{let r=await t.revokeSession(n);return await e(),r},[t,e]),o=useCallback(async()=>{let n=await t.revokeOtherSessions();return await e(),n},[t,e]);return useEffect(()=>{e();},[e]),{sessions:A,isLoading:f,error:c,revokeSession:h,revokeOtherSessions:o,refresh:e}}export{k as AuthProvider,L as useAuth,S as useAuthClient,V as useIdentities,U as useIsAuthenticated,R as useMFA,T as usePassword,W as useSession,N as useSessions,b as useUser};
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vaiftech/auth",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Comprehensive authentication SDK for VAIF - Session management, OAuth, MFA, and more",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./react": {
|
|
15
|
+
"types": "./dist/react.d.ts",
|
|
16
|
+
"import": "./dist/react.mjs",
|
|
17
|
+
"require": "./dist/react.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"dev": "tsup --watch",
|
|
26
|
+
"lint": "tsc --noEmit",
|
|
27
|
+
"typecheck": "tsc --noEmit"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^22.14.0",
|
|
31
|
+
"@types/react": "^18.2.0",
|
|
32
|
+
"react": "^18.2.0",
|
|
33
|
+
"tsup": "^8.5.1",
|
|
34
|
+
"typescript": "^5.5.4"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": ">=18.0.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependenciesMeta": {
|
|
40
|
+
"react": {
|
|
41
|
+
"optional": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=19.0.0"
|
|
46
|
+
},
|
|
47
|
+
"keywords": [
|
|
48
|
+
"vaif",
|
|
49
|
+
"auth",
|
|
50
|
+
"authentication",
|
|
51
|
+
"oauth",
|
|
52
|
+
"jwt",
|
|
53
|
+
"session",
|
|
54
|
+
"mfa",
|
|
55
|
+
"two-factor",
|
|
56
|
+
"social-login",
|
|
57
|
+
"magic-link",
|
|
58
|
+
"passwordless"
|
|
59
|
+
],
|
|
60
|
+
"author": "VAIF Technologies",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"repository": {
|
|
63
|
+
"type": "git",
|
|
64
|
+
"url": "https://github.com/vaifllc/vaif-studio",
|
|
65
|
+
"directory": "packages/auth"
|
|
66
|
+
},
|
|
67
|
+
"bugs": {
|
|
68
|
+
"url": "https://github.com/vaifllc/vaif-studio/issues"
|
|
69
|
+
},
|
|
70
|
+
"homepage": "https://vaif.studio"
|
|
71
|
+
}
|