mulguard 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -185,6 +185,40 @@ export const auth = mulguard({
185
185
  // Log errors for monitoring
186
186
  console.error(`Auth error in ${context}:`, error)
187
187
  },
188
+ // ✅ OAuth callback: receives userInfo with accessToken, refreshToken, profile, etc.
189
+ onOAuthUser: async (userInfo, provider) => {
190
+ // Backend API example:
191
+ // const response = await fetch('/api/v1/auth/oauth/callback', {
192
+ // method: 'POST',
193
+ // body: JSON.stringify({
194
+ // provider,
195
+ // access_token: userInfo.accessToken,
196
+ // refresh_token: userInfo.refreshToken,
197
+ // profile: userInfo,
198
+ // email: userInfo.email,
199
+ // })
200
+ // })
201
+ // return await response.json()
202
+
203
+ // Database example:
204
+ let user = await db.user.findUnique({ where: { email: userInfo.email } })
205
+ if (!user) {
206
+ user = await db.user.create({
207
+ data: {
208
+ email: userInfo.email,
209
+ name: userInfo.name,
210
+ emailVerified: userInfo.emailVerified,
211
+ oauthProvider: provider,
212
+ }
213
+ })
214
+ }
215
+ return {
216
+ id: user.id,
217
+ email: user.email,
218
+ name: user.name,
219
+ emailVerified: user.emailVerified,
220
+ }
221
+ },
188
222
  },
189
223
  })
190
224
  ```
@@ -599,28 +633,30 @@ export function AuthComponent() {
599
633
  }
600
634
  ```
601
635
 
602
- ### Auth Provider
636
+ ### Mulguard Provider
603
637
 
604
638
  ```typescript
605
639
  // app/layout.tsx
606
640
  'use client'
607
641
 
608
- import { AuthProvider } from 'mulguard/client'
642
+ import { MulguardProvider } from 'mulguard/client'
609
643
  import { auth } from '@/lib/auth'
610
644
 
611
645
  export default function RootLayout({ children }) {
612
646
  return (
613
647
  <html>
614
648
  <body>
615
- <AuthProvider auth={auth}>
649
+ <MulguardProvider auth={auth}>
616
650
  {children}
617
- </AuthProvider>
651
+ </MulguardProvider>
618
652
  </body>
619
653
  </html>
620
654
  )
621
655
  }
622
656
  ```
623
657
 
658
+ > **Note:** `AuthProvider` is still available for backward compatibility but is deprecated. Use `MulguardProvider` instead.
659
+
624
660
  ---
625
661
 
626
662
  ## 🎨 Components
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),x=require("react/jsx-runtime");function h(){return typeof window>"u"}async function v(){try{return await Promise.resolve().then(()=>require("../actions-CExpv_dD.js")).then(l=>l.actions)}catch{return null}}async function O(e,l){if(h())return e.verify2FA?e.verify2FA(l):{success:!1,error:"2FA verification is not configured"};try{const r=await v();if(r)return await r.verify2FAAction(e,l)}catch{}try{const r=await fetch("/api/auth/verify-2fa",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(l)});if(!r.ok){const a=await r.json().catch(()=>({}));return{success:!1,error:a.error||"2FA verification failed",errorCode:a.errorCode}}return await r.json()}catch(r){return{success:!1,error:r instanceof Error?r.message:"2FA verification failed"}}}async function N(e,l){var r;if(h())return(r=e.signIn)!=null&&r.email?e.signIn.email(l):{success:!1,error:"Email sign in is not configured"};try{const a=await v();if(a)return await a.signInEmailAction(e,l)}catch{}try{const a=await fetch("/api/auth/sign-in",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({provider:"email",credentials:l})});if(!a.ok){const u=await a.json().catch(()=>({}));return{success:!1,error:u.error||"Sign in failed",errorCode:u.errorCode}}return await a.json()}catch(a){return{success:!1,error:a instanceof Error?a.message:"Sign in failed"}}}async function _(e,l){if(h())return e.signUp?e.signUp(l):{success:!1,error:"Sign up is not configured"};try{const r=await v();if(r)return await r.signUpAction(e,l)}catch{}try{const r=await fetch("/api/auth/sign-up",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(l)});if(!r.ok){const a=await r.json().catch(()=>({}));return{success:!1,error:a.error||"Sign up failed",errorCode:a.errorCode}}return await r.json()}catch(r){return{success:!1,error:r instanceof Error?r.message:"Sign up failed"}}}function A(e){const[l,r]=o.useState(null),[a,u]=o.useState(!0),c=o.useCallback(async(s=!1)=>{u(!0);try{const n="/api/auth/session"+(s?`?t=${Date.now()}`:""),i=await fetch(n,{method:"GET",credentials:"include",headers:{"Content-Type":"application/json","Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:"0"},cache:"no-store"});if(i.status===401||i.status===403){r(null);return}if(i.ok){const t=await i.json();t.session?r(t.session):r(null)}else r(null)}catch(n){process.env.NODE_ENV==="development"&&console.error("Failed to load session:",n),r(null)}finally{u(!1)}},[e]),g=o.useCallback(s=>{if(!s||!s.expiresAt||!e.refreshSession)return()=>{};const n=new Date(s.expiresAt),i=new Date,t=n.getTime()-i.getTime(),f=5*60*1e3;if(t>0&&t<f)return e.refreshSession().catch(()=>{}),()=>{};if(t>f){const p=t-f,k=setTimeout(()=>{var S;(S=e.refreshSession)==null||S.call(e).catch(()=>{})},p);return()=>clearTimeout(k)}return()=>{}},[e]);o.useEffect(()=>{let s=null;(async()=>{await c();try{const t=await fetch("/api/auth/session",{method:"GET",credentials:"include",headers:{"Content-Type":"application/json"},cache:"no-store"});if(t.ok){const f=await t.json();f.session?s=g(f.session):r(null)}else r(null)}catch(t){process.env.NODE_ENV==="development"&&console.debug("Failed to schedule proactive refresh:",t),r(null)}})();const i=setInterval(()=>{fetch("/api/auth/session",{method:"GET",credentials:"include",headers:{"Content-Type":"application/json"},cache:"no-store"}).then(t=>t.status===401||t.status===403?(r(null),s&&(s(),s=null),typeof window<"u"&&window.location.pathname!=="/auth/login"&&window.location.replace("/auth/login?reason=session_expired"),null):t.json()).then(t=>{t&&(t.session?(r(t.session),s&&s(),s=g(t.session)):(r(null),s&&(s(),s=null)))}).catch(()=>{r(null),s&&(s(),s=null)})},60*1e3);return()=>{clearInterval(i),s&&s()}},[c,g]);const y=o.useCallback(async s=>{try{const n=await N(e,s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"Sign in failed"}}},[e,c]),w=o.useCallback(async s=>{if(!e.signIn.oauth)throw new Error("OAuth sign in is not configured");return e.signIn.oauth(s)},[e]),d=o.useCallback(async s=>{if(!e.signIn.passkey)return{success:!1,error:"PassKey sign in is not configured"};try{const n=await e.signIn.passkey(s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"PassKey authentication failed"}}},[e,c]),m=o.useCallback(async s=>{if(!e.signUp)return{success:!1,error:"Sign up is not configured"};try{const n=await _(e,s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"Sign up failed"}}},[e,c]),I=o.useCallback(async()=>{var s,n;try{if(r(null),u(!0),typeof window<"u"){try{window.sessionStorage.clear()}catch{}try{const i=(s=e._getSessionConfig)==null?void 0:s.call(e),t=(i==null?void 0:i.cookieName)||"__mulguard_session";try{window.localStorage.removeItem(t)}catch{}}catch{}}if(await e.signOut(),await c(!0),r(null),u(!1),typeof window<"u"){const i="/auth/login",t=window.location.pathname,f=window.location.search;if(t===i||t.startsWith("/auth/")){window.location.reload();return}const p=new URL(i,window.location.origin);t&&t!=="/"&&p.searchParams.set("redirect",t+f),window.location.replace(p.toString())}}catch(i){if(process.env.NODE_ENV==="development"&&console.error("Sign out error:",i),r(null),u(!1),typeof window<"u"){try{window.sessionStorage.clear();const f=(n=e._getSessionConfig)==null?void 0:n.call(e),p=(f==null?void 0:f.cookieName)||"__mulguard_session";try{window.localStorage.removeItem(p)}catch{}}catch{}const t="/auth/login";window.location.pathname!==t&&!window.location.pathname.startsWith("/auth/")?window.location.replace(t):window.location.reload()}}},[e,c]),U=o.useCallback(async s=>{if(!e.resetPassword)throw new Error("Password reset is not configured");return e.resetPassword(s)},[e]),T=o.useCallback(async s=>{if(!e.verifyEmail)throw new Error("Email verification is not configured");return e.verifyEmail(s)},[e]),F=o.useCallback(async s=>{if(!e.verify2FA)return{success:!1,error:"2FA verification is not configured"};try{const n=await O(e,s);return n.success&&(await new Promise(i=>setTimeout(i,100)),await c()),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"2FA verification failed"}}},[e,c]),j=o.useCallback(async(s,n)=>e.signIn(s,n),[e]);return{session:l,isLoading:a,signIn:j,signInMethods:{email:y,oauth:w,passkey:d,otp:o.useCallback(async(s,n)=>{if(!e.signIn.otp)return{success:!1,error:"OTP sign in is not configured"};try{const i=await e.signIn.otp(s,n);return i.success&&await c(),i}catch(i){return{success:!1,error:i instanceof Error?i.message:"OTP sign in failed"}}},[e,c])},signUp:m,signOut:I,resetPassword:U,verifyEmail:T,verify2FA:F}}function C(e){const[l,r]=o.useState(null),[a,u]=o.useState(!0),[c,g]=o.useState(null),y=o.useCallback(async()=>{u(!0),g(null);try{const w=await e.getSession();r(w)}catch(w){const d=w instanceof Error?w:new Error("Failed to load session");g(d),r(null)}finally{u(!1)}},[e]);return o.useEffect(()=>{y();const w=setInterval(()=>{y()},5*60*1e3);return()=>clearInterval(w)},[y]),{session:l,isLoading:a,error:c}}function E(e){const[l,r]=o.useState([]),[a,u]=o.useState(!0),c=o.useCallback(async()=>{if(!e.accountPicker){r([]),u(!1);return}u(!0);try{const d=await e.accountPicker.getLastUsers();r(d)}catch(d){process.env.NODE_ENV==="development"&&console.error("Failed to load last users:",d),r([])}finally{u(!1)}},[e]);o.useEffect(()=>{c()},[c]);const g=o.useCallback(async(d,m)=>{e.accountPicker&&(await e.accountPicker.rememberUser(d,m),await c())},[e,c]),y=o.useCallback(async d=>{e.accountPicker&&(await e.accountPicker.clearUser(d),await c())},[e,c]),w=o.useCallback(async()=>{e.accountPicker&&(await e.accountPicker.clearAll(),await c())},[e,c]);return{lastUsers:l,isLoading:a,rememberUser:g,clearUser:y,clearAll:w,refresh:c}}const P=o.createContext(null);function D({auth:e,children:l}){const r=C(e),a=E(e);return x.jsx(P.Provider,{value:{auth:e,session:r,accountPicker:a},children:l})}function b(){const e=o.useContext(P);if(!e)throw new Error("useAuthContext must be used within AuthProvider");return e}function L(){const{auth:e}=b();return A(e)}exports.AuthProvider=D;exports.useAccountPicker=E;exports.useAuth=A;exports.useAuthContext=b;exports.useAuthFromContext=L;exports.useSession=C;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),O=require("react/jsx-runtime");function v(){return typeof window>"u"}async function h(){try{return await Promise.resolve().then(()=>require("../actions-CExpv_dD.js")).then(l=>l.actions)}catch{return null}}async function N(e,l){if(v())return e.verify2FA?e.verify2FA(l):{success:!1,error:"2FA verification is not configured"};try{const r=await h();if(r)return await r.verify2FAAction(e,l)}catch{}try{const r=await fetch("/api/auth/verify-2fa",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(l)});if(!r.ok){const a=await r.json().catch(()=>({}));return{success:!1,error:a.error||"2FA verification failed",errorCode:a.errorCode}}return await r.json()}catch(r){return{success:!1,error:r instanceof Error?r.message:"2FA verification failed"}}}async function _(e,l){var r;if(v())return(r=e.signIn)!=null&&r.email?e.signIn.email(l):{success:!1,error:"Email sign in is not configured"};try{const a=await h();if(a)return await a.signInEmailAction(e,l)}catch{}try{const a=await fetch("/api/auth/sign-in",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({provider:"email",credentials:l})});if(!a.ok){const u=await a.json().catch(()=>({}));return{success:!1,error:u.error||"Sign in failed",errorCode:u.errorCode}}return await a.json()}catch(a){return{success:!1,error:a instanceof Error?a.message:"Sign in failed"}}}async function D(e,l){if(v())return e.signUp?e.signUp(l):{success:!1,error:"Sign up is not configured"};try{const r=await h();if(r)return await r.signUpAction(e,l)}catch{}try{const r=await fetch("/api/auth/sign-up",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(l)});if(!r.ok){const a=await r.json().catch(()=>({}));return{success:!1,error:a.error||"Sign up failed",errorCode:a.errorCode}}return await r.json()}catch(r){return{success:!1,error:r instanceof Error?r.message:"Sign up failed"}}}function E(e){const[l,r]=o.useState(null),[a,u]=o.useState(!0),c=o.useCallback(async(s=!1)=>{u(!0);try{const n="/api/auth/session"+(s?`?t=${Date.now()}`:""),i=await fetch(n,{method:"GET",credentials:"include",headers:{"Content-Type":"application/json","Cache-Control":"no-cache, no-store, must-revalidate",Pragma:"no-cache",Expires:"0"},cache:"no-store"});if(i.status===401||i.status===403){r(null);return}if(i.ok){const t=await i.json();t.session?r(t.session):r(null)}else r(null)}catch(n){process.env.NODE_ENV==="development"&&console.error("Failed to load session:",n),r(null)}finally{u(!1)}},[e]),g=o.useCallback(s=>{if(!s||!s.expiresAt||!e.refreshSession)return()=>{};const n=new Date(s.expiresAt),i=new Date,t=n.getTime()-i.getTime(),f=5*60*1e3;if(t>0&&t<f)return e.refreshSession().catch(()=>{}),()=>{};if(t>f){const p=t-f,S=setTimeout(()=>{var C;(C=e.refreshSession)==null||C.call(e).catch(()=>{})},p);return()=>clearTimeout(S)}return()=>{}},[e]);o.useEffect(()=>{let s=null;(async()=>{await c();try{const t=await fetch("/api/auth/session",{method:"GET",credentials:"include",headers:{"Content-Type":"application/json"},cache:"no-store"});if(t.ok){const f=await t.json();f.session?s=g(f.session):r(null)}else r(null)}catch(t){process.env.NODE_ENV==="development"&&console.debug("Failed to schedule proactive refresh:",t),r(null)}})();const i=setInterval(()=>{fetch("/api/auth/session",{method:"GET",credentials:"include",headers:{"Content-Type":"application/json"},cache:"no-store"}).then(t=>t.status===401||t.status===403?(r(null),s&&(s(),s=null),typeof window<"u"&&window.location.pathname!=="/auth/login"&&window.location.replace("/auth/login?reason=session_expired"),null):t.json()).then(t=>{t&&(t.session?(r(t.session),s&&s(),s=g(t.session)):(r(null),s&&(s(),s=null)))}).catch(()=>{r(null),s&&(s(),s=null)})},60*1e3);return()=>{clearInterval(i),s&&s()}},[c,g]);const y=o.useCallback(async s=>{try{const n=await _(e,s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"Sign in failed"}}},[e,c]),w=o.useCallback(async s=>{if(!e.signIn.oauth)throw new Error("OAuth sign in is not configured");return e.signIn.oauth(s)},[e]),d=o.useCallback(async s=>{if(!e.signIn.passkey)return{success:!1,error:"PassKey sign in is not configured"};try{const n=await e.signIn.passkey(s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"PassKey authentication failed"}}},[e,c]),m=o.useCallback(async s=>{if(!e.signUp)return{success:!1,error:"Sign up is not configured"};try{const n=await D(e,s);return n.success&&await c(),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"Sign up failed"}}},[e,c]),U=o.useCallback(async()=>{var s,n;try{if(r(null),u(!0),typeof window<"u"){try{window.sessionStorage.clear()}catch{}try{const i=(s=e._getSessionConfig)==null?void 0:s.call(e),t=(i==null?void 0:i.cookieName)||"__mulguard_session";try{window.localStorage.removeItem(t)}catch{}}catch{}}if(await e.signOut(),await c(!0),r(null),u(!1),typeof window<"u"){const i="/auth/login",t=window.location.pathname,f=window.location.search;if(t===i||t.startsWith("/auth/")){window.location.reload();return}const p=new URL(i,window.location.origin);t&&t!=="/"&&p.searchParams.set("redirect",t+f),window.location.replace(p.toString())}}catch(i){if(process.env.NODE_ENV==="development"&&console.error("Sign out error:",i),r(null),u(!1),typeof window<"u"){try{window.sessionStorage.clear();const f=(n=e._getSessionConfig)==null?void 0:n.call(e),p=(f==null?void 0:f.cookieName)||"__mulguard_session";try{window.localStorage.removeItem(p)}catch{}}catch{}const t="/auth/login";window.location.pathname!==t&&!window.location.pathname.startsWith("/auth/")?window.location.replace(t):window.location.reload()}}},[e,c]),T=o.useCallback(async s=>{if(!e.resetPassword)throw new Error("Password reset is not configured");return e.resetPassword(s)},[e]),F=o.useCallback(async s=>{if(!e.verifyEmail)throw new Error("Email verification is not configured");return e.verifyEmail(s)},[e]),x=o.useCallback(async s=>{if(!e.verify2FA)return{success:!1,error:"2FA verification is not configured"};try{const n=await N(e,s);return n.success&&(await new Promise(i=>setTimeout(i,100)),await c()),n}catch(n){return{success:!1,error:n instanceof Error?n.message:"2FA verification failed"}}},[e,c]),j=o.useCallback(async(s,n)=>e.signIn(s,n),[e]);return{session:l,isLoading:a,signIn:j,signInMethods:{email:y,oauth:w,passkey:d,otp:o.useCallback(async(s,n)=>{if(!e.signIn.otp)return{success:!1,error:"OTP sign in is not configured"};try{const i=await e.signIn.otp(s,n);return i.success&&await c(),i}catch(i){return{success:!1,error:i instanceof Error?i.message:"OTP sign in failed"}}},[e,c])},signUp:m,signOut:U,resetPassword:T,verifyEmail:F,verify2FA:x}}function A(e){const[l,r]=o.useState(null),[a,u]=o.useState(!0),[c,g]=o.useState(null),y=o.useCallback(async()=>{u(!0),g(null);try{const w=await e.getSession();r(w)}catch(w){const d=w instanceof Error?w:new Error("Failed to load session");g(d),r(null)}finally{u(!1)}},[e]);return o.useEffect(()=>{y();const w=setInterval(()=>{y()},5*60*1e3);return()=>clearInterval(w)},[y]),{session:l,isLoading:a,error:c}}function P(e){const[l,r]=o.useState([]),[a,u]=o.useState(!0),c=o.useCallback(async()=>{if(!e.accountPicker){r([]),u(!1);return}u(!0);try{const d=await e.accountPicker.getLastUsers();r(d)}catch(d){process.env.NODE_ENV==="development"&&console.error("Failed to load last users:",d),r([])}finally{u(!1)}},[e]);o.useEffect(()=>{c()},[c]);const g=o.useCallback(async(d,m)=>{e.accountPicker&&(await e.accountPicker.rememberUser(d,m),await c())},[e,c]),y=o.useCallback(async d=>{e.accountPicker&&(await e.accountPicker.clearUser(d),await c())},[e,c]),w=o.useCallback(async()=>{e.accountPicker&&(await e.accountPicker.clearAll(),await c())},[e,c]);return{lastUsers:l,isLoading:a,rememberUser:g,clearUser:y,clearAll:w,refresh:c}}const b=o.createContext(null);function I({auth:e,children:l}){const r=A(e),a=P(e);return O.jsx(b.Provider,{value:{auth:e,session:r,accountPicker:a},children:l})}function k(){const e=o.useContext(b);if(!e)throw new Error("useMulguardContext must be used within MulguardProvider");return e}function L(){const{auth:e}=k();return E(e)}const M=I,R=k;exports.AuthProvider=M;exports.MulguardProvider=I;exports.useAccountPicker=P;exports.useAuth=E;exports.useAuthContext=R;exports.useAuthFromContext=L;exports.useMulguardContext=k;exports.useSession=A;
@@ -1,5 +1,5 @@
1
- import { useState as y, useCallback as l, useEffect as v, createContext as j, useContext as O } from "react";
2
- import { jsx as x } from "react/jsx-runtime";
1
+ import { useState as y, useCallback as l, useEffect as h, createContext as x, useContext as O } from "react";
2
+ import { jsx as N } from "react/jsx-runtime";
3
3
  function E() {
4
4
  return typeof window > "u";
5
5
  }
@@ -10,7 +10,7 @@ async function S() {
10
10
  return null;
11
11
  }
12
12
  }
13
- async function N(e, a) {
13
+ async function _(e, a) {
14
14
  if (E())
15
15
  return e.verify2FA ? e.verify2FA(a) : {
16
16
  success: !1,
@@ -47,7 +47,7 @@ async function N(e, a) {
47
47
  };
48
48
  }
49
49
  }
50
- async function _(e, a) {
50
+ async function b(e, a) {
51
51
  var r;
52
52
  if (E())
53
53
  return (r = e.signIn) != null && r.email ? e.signIn.email(a) : {
@@ -85,7 +85,7 @@ async function _(e, a) {
85
85
  };
86
86
  }
87
87
  }
88
- async function b(e, a) {
88
+ async function D(e, a) {
89
89
  if (E())
90
90
  return e.signUp ? e.signUp(a) : {
91
91
  success: !1,
@@ -122,7 +122,7 @@ async function b(e, a) {
122
122
  };
123
123
  }
124
124
  }
125
- function D(e) {
125
+ function L(e) {
126
126
  const [a, r] = y(null), [c, f] = y(!0), i = l(async (n = !1) => {
127
127
  f(!0);
128
128
  try {
@@ -174,7 +174,7 @@ function D(e) {
174
174
  return () => {
175
175
  };
176
176
  }, [e]);
177
- v(() => {
177
+ h(() => {
178
178
  let n = null;
179
179
  (async () => {
180
180
  await i();
@@ -219,7 +219,7 @@ function D(e) {
219
219
  const p = l(
220
220
  async (n) => {
221
221
  try {
222
- const s = await _(e, n);
222
+ const s = await b(e, n);
223
223
  return s.success && await i(), s;
224
224
  } catch (s) {
225
225
  return {
@@ -254,7 +254,7 @@ function D(e) {
254
254
  }
255
255
  },
256
256
  [e, i]
257
- ), h = l(
257
+ ), v = l(
258
258
  async (n) => {
259
259
  if (!e.signUp)
260
260
  return {
@@ -262,7 +262,7 @@ function D(e) {
262
262
  error: "Sign up is not configured"
263
263
  };
264
264
  try {
265
- const s = await b(e, n);
265
+ const s = await D(e, n);
266
266
  return s.success && await i(), s;
267
267
  } catch (s) {
268
268
  return {
@@ -272,7 +272,7 @@ function D(e) {
272
272
  }
273
273
  },
274
274
  [e, i]
275
- ), k = l(async () => {
275
+ ), C = l(async () => {
276
276
  var n, s;
277
277
  try {
278
278
  if (r(null), f(!0), typeof window < "u") {
@@ -320,14 +320,14 @@ function D(e) {
320
320
  return e.resetPassword(n);
321
321
  },
322
322
  [e]
323
- ), C = l(
323
+ ), T = l(
324
324
  async (n) => {
325
325
  if (!e.verifyEmail)
326
326
  throw new Error("Email verification is not configured");
327
327
  return e.verifyEmail(n);
328
328
  },
329
329
  [e]
330
- ), T = l(
330
+ ), F = l(
331
331
  async (n) => {
332
332
  if (!e.verify2FA)
333
333
  return {
@@ -335,7 +335,7 @@ function D(e) {
335
335
  error: "2FA verification is not configured"
336
336
  };
337
337
  try {
338
- const s = await N(e, n);
338
+ const s = await _(e, n);
339
339
  return s.success && (await new Promise((t) => setTimeout(t, 100)), await i()), s;
340
340
  } catch (s) {
341
341
  return {
@@ -345,14 +345,14 @@ function D(e) {
345
345
  }
346
346
  },
347
347
  [e, i]
348
- ), F = l(
348
+ ), j = l(
349
349
  async (n, s) => e.signIn(n, s),
350
350
  [e]
351
351
  );
352
352
  return {
353
353
  session: a,
354
354
  isLoading: c,
355
- signIn: F,
355
+ signIn: j,
356
356
  signInMethods: {
357
357
  email: p,
358
358
  oauth: w,
@@ -377,14 +377,14 @@ function D(e) {
377
377
  [e, i]
378
378
  )
379
379
  },
380
- signUp: h,
381
- signOut: k,
380
+ signUp: v,
381
+ signOut: C,
382
382
  resetPassword: U,
383
- verifyEmail: C,
384
- verify2FA: T
383
+ verifyEmail: T,
384
+ verify2FA: F
385
385
  };
386
386
  }
387
- function L(e) {
387
+ function M(e) {
388
388
  const [a, r] = y(null), [c, f] = y(!0), [i, g] = y(null), p = l(async () => {
389
389
  f(!0), g(null);
390
390
  try {
@@ -397,7 +397,7 @@ function L(e) {
397
397
  f(!1);
398
398
  }
399
399
  }, [e]);
400
- return v(() => {
400
+ return h(() => {
401
401
  p();
402
402
  const w = setInterval(() => {
403
403
  p();
@@ -425,12 +425,12 @@ function W(e) {
425
425
  f(!1);
426
426
  }
427
427
  }, [e]);
428
- v(() => {
428
+ h(() => {
429
429
  i();
430
430
  }, [i]);
431
431
  const g = l(
432
- async (d, h) => {
433
- e.accountPicker && (await e.accountPicker.rememberUser(d, h), await i());
432
+ async (d, v) => {
433
+ e.accountPicker && (await e.accountPicker.rememberUser(d, v), await i());
434
434
  },
435
435
  [e, i]
436
436
  ), p = l(
@@ -450,26 +450,29 @@ function W(e) {
450
450
  refresh: i
451
451
  };
452
452
  }
453
- const I = j(null);
454
- function J({ auth: e, children: a }) {
455
- const r = L(e), c = W(e);
456
- return /* @__PURE__ */ x(I.Provider, { value: { auth: e, session: r, accountPicker: c }, children: a });
453
+ const I = x(null);
454
+ function R({ auth: e, children: a }) {
455
+ const r = M(e), c = W(e);
456
+ return /* @__PURE__ */ N(I.Provider, { value: { auth: e, session: r, accountPicker: c }, children: a });
457
457
  }
458
- function R() {
458
+ function k() {
459
459
  const e = O(I);
460
460
  if (!e)
461
- throw new Error("useAuthContext must be used within AuthProvider");
461
+ throw new Error("useMulguardContext must be used within MulguardProvider");
462
462
  return e;
463
463
  }
464
- function z() {
465
- const { auth: e } = R();
466
- return D(e);
464
+ function J() {
465
+ const { auth: e } = k();
466
+ return L(e);
467
467
  }
468
+ const z = R, K = k;
468
469
  export {
469
- J as AuthProvider,
470
+ z as AuthProvider,
471
+ R as MulguardProvider,
470
472
  W as useAccountPicker,
471
- D as useAuth,
472
- R as useAuthContext,
473
- z as useAuthFromContext,
474
- L as useSession
473
+ L as useAuth,
474
+ K as useAuthContext,
475
+ J as useAuthFromContext,
476
+ k as useMulguardContext,
477
+ M as useSession
475
478
  };
@@ -1,25 +1,69 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { MulguardInstance } from '../mulguard';
3
3
  import { useSession, useAccountPicker } from './hooks';
4
- interface AuthContextValue {
4
+ interface MulguardContextValue {
5
5
  auth: MulguardInstance;
6
6
  session: ReturnType<typeof useSession>;
7
7
  accountPicker: ReturnType<typeof useAccountPicker>;
8
8
  }
9
- interface AuthProviderProps {
9
+ interface MulguardProviderProps {
10
10
  auth: MulguardInstance;
11
11
  children: ReactNode;
12
12
  }
13
13
  /**
14
- * Auth Provider - provides auth instance to children
14
+ * Mulguard Provider - provides auth instance to children
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * import { MulguardProvider } from 'mulguard/client'
19
+ * import { auth } from '@/lib/auth'
20
+ *
21
+ * export default function RootLayout({ children }) {
22
+ * return (
23
+ * <MulguardProvider auth={auth}>
24
+ * {children}
25
+ * </MulguardProvider>
26
+ * )
27
+ * }
28
+ * ```
15
29
  */
16
- export declare function AuthProvider({ auth, children }: AuthProviderProps): import("react/jsx-runtime").JSX.Element;
30
+ export declare function MulguardProvider({ auth, children }: MulguardProviderProps): import("react/jsx-runtime").JSX.Element;
17
31
  /**
18
- * Use auth context
32
+ * Use Mulguard context
33
+ *
34
+ * @example
35
+ * ```tsx
36
+ * import { useMulguardContext } from 'mulguard/client'
37
+ *
38
+ * function Component() {
39
+ * const { auth, session } = useMulguardContext()
40
+ * // ...
41
+ * }
42
+ * ```
19
43
  */
20
- export declare function useAuthContext(): AuthContextValue;
44
+ export declare function useMulguardContext(): MulguardContextValue;
21
45
  /**
22
46
  * Convenience hook that uses context
47
+ *
48
+ * @example
49
+ * ```tsx
50
+ * import { useAuthFromContext } from 'mulguard/client'
51
+ *
52
+ * function Component() {
53
+ * const { signIn, signOut } = useAuthFromContext()
54
+ * // ...
55
+ * }
56
+ * ```
23
57
  */
24
58
  export declare function useAuthFromContext(): import('./hooks').UseAuthReturn;
59
+ /**
60
+ * @deprecated Use MulguardProvider instead
61
+ * This is kept for backward compatibility
62
+ */
63
+ export declare const AuthProvider: typeof MulguardProvider;
64
+ /**
65
+ * @deprecated Use useMulguardContext instead
66
+ * This is kept for backward compatibility
67
+ */
68
+ export declare const useAuthContext: typeof useMulguardContext;
25
69
  export {};
@@ -58,6 +58,7 @@ export declare function exchangeOAuthCode(providerId: string, config: OAuthProvi
58
58
  }>;
59
59
  /**
60
60
  * Get user info from OAuth provider
61
+ * Returns normalized user info with raw profile data
61
62
  */
62
63
  export declare function getOAuthUserInfo(providerId: string, accessToken: string): Promise<{
63
64
  id: string;
@@ -65,5 +66,6 @@ export declare function getOAuthUserInfo(providerId: string, accessToken: string
65
66
  name: string;
66
67
  avatar?: string;
67
68
  emailVerified?: boolean;
69
+ rawProfile: Record<string, unknown>;
68
70
  }>;
69
71
  export {};
@@ -272,15 +272,44 @@ export interface SecurityConfig {
272
272
  /** Allowed origins for CORS */
273
273
  allowedOrigins?: string[];
274
274
  }
275
+ /**
276
+ * OAuth tokens from provider
277
+ */
278
+ export interface OAuthTokens {
279
+ access_token: string;
280
+ refresh_token?: string;
281
+ expires_in?: number;
282
+ token_type?: string;
283
+ id_token?: string;
284
+ scope?: string;
285
+ }
275
286
  /**
276
287
  * OAuth user info from provider
288
+ * Enhanced with tokens and provider information for maximum flexibility
277
289
  */
278
290
  export interface OAuthUserInfo {
291
+ /** User ID from OAuth provider */
279
292
  id: string;
293
+ /** User email from OAuth provider */
280
294
  email: string;
295
+ /** User name from OAuth provider */
281
296
  name: string;
297
+ /** User avatar URL (optional) */
282
298
  avatar?: string;
299
+ /** Whether email is verified (optional) */
283
300
  emailVerified?: boolean;
301
+ /** ✅ NEW: OAuth provider name (e.g., 'google', 'github') */
302
+ provider: string;
303
+ /** ✅ NEW: Access token from OAuth provider (required for backend API integration) */
304
+ accessToken: string;
305
+ /** ✅ NEW: Refresh token from OAuth provider (optional, for token refresh) */
306
+ refreshToken?: string;
307
+ /** ✅ NEW: Complete tokens object with all token information */
308
+ tokens: OAuthTokens;
309
+ /** ✅ NEW: Raw profile data from OAuth provider (for advanced use cases) */
310
+ rawProfile?: Record<string, unknown>;
311
+ /** ✅ NEW: Additional provider-specific fields */
312
+ [key: string]: unknown;
284
313
  }
285
314
  /**
286
315
  * Callbacks configuration