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 +40 -4
- package/dist/client/index.js +1 -1
- package/dist/client/index.mjs +42 -39
- package/dist/client/provider.d.ts +50 -6
- package/dist/core/auth/oauth-providers.d.ts +2 -0
- package/dist/core/types/index.d.ts +29 -0
- package/dist/index/index.js +1 -1
- package/dist/index/index.mjs +328 -301
- package/package.json +1 -1
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
|
-
###
|
|
636
|
+
### Mulguard Provider
|
|
603
637
|
|
|
604
638
|
```typescript
|
|
605
639
|
// app/layout.tsx
|
|
606
640
|
'use client'
|
|
607
641
|
|
|
608
|
-
import {
|
|
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
|
-
<
|
|
649
|
+
<MulguardProvider auth={auth}>
|
|
616
650
|
{children}
|
|
617
|
-
</
|
|
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
|
package/dist/client/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),
|
|
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;
|
package/dist/client/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useState as y, useCallback as l, useEffect as
|
|
2
|
-
import { jsx as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
),
|
|
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
|
|
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
|
-
),
|
|
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
|
-
),
|
|
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
|
-
),
|
|
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
|
|
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
|
-
),
|
|
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:
|
|
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:
|
|
381
|
-
signOut:
|
|
380
|
+
signUp: v,
|
|
381
|
+
signOut: C,
|
|
382
382
|
resetPassword: U,
|
|
383
|
-
verifyEmail:
|
|
384
|
-
verify2FA:
|
|
383
|
+
verifyEmail: T,
|
|
384
|
+
verify2FA: F
|
|
385
385
|
};
|
|
386
386
|
}
|
|
387
|
-
function
|
|
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
|
|
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
|
-
|
|
428
|
+
h(() => {
|
|
429
429
|
i();
|
|
430
430
|
}, [i]);
|
|
431
431
|
const g = l(
|
|
432
|
-
async (d,
|
|
433
|
-
e.accountPicker && (await e.accountPicker.rememberUser(d,
|
|
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 =
|
|
454
|
-
function
|
|
455
|
-
const r =
|
|
456
|
-
return /* @__PURE__ */
|
|
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
|
|
458
|
+
function k() {
|
|
459
459
|
const e = O(I);
|
|
460
460
|
if (!e)
|
|
461
|
-
throw new Error("
|
|
461
|
+
throw new Error("useMulguardContext must be used within MulguardProvider");
|
|
462
462
|
return e;
|
|
463
463
|
}
|
|
464
|
-
function
|
|
465
|
-
const { auth: e } =
|
|
466
|
-
return
|
|
464
|
+
function J() {
|
|
465
|
+
const { auth: e } = k();
|
|
466
|
+
return L(e);
|
|
467
467
|
}
|
|
468
|
+
const z = R, K = k;
|
|
468
469
|
export {
|
|
469
|
-
|
|
470
|
+
z as AuthProvider,
|
|
471
|
+
R as MulguardProvider,
|
|
470
472
|
W as useAccountPicker,
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
|
4
|
+
interface MulguardContextValue {
|
|
5
5
|
auth: MulguardInstance;
|
|
6
6
|
session: ReturnType<typeof useSession>;
|
|
7
7
|
accountPicker: ReturnType<typeof useAccountPicker>;
|
|
8
8
|
}
|
|
9
|
-
interface
|
|
9
|
+
interface MulguardProviderProps {
|
|
10
10
|
auth: MulguardInstance;
|
|
11
11
|
children: ReactNode;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
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
|
|
30
|
+
export declare function MulguardProvider({ auth, children }: MulguardProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
17
31
|
/**
|
|
18
|
-
* Use
|
|
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
|
|
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
|