@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.
@@ -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';
@@ -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 };
@@ -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
+ }