next-api-layer 0.1.8 → 0.1.10
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 +44 -0
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +32 -2
- package/dist/client.d.ts +32 -2
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -419,6 +419,8 @@ interface AuthProxyConfig {
|
|
|
419
419
|
protectedRoutes?: string[]; // Routes requiring auth
|
|
420
420
|
authRoutes?: string[]; // Routes for non-auth users (login, register)
|
|
421
421
|
publicRoutes?: string[]; // Completely public routes
|
|
422
|
+
// Note: Locale prefix is automatically stripped before matching
|
|
423
|
+
// e.g., '/tr/login' matches config '/login' when i18n is enabled
|
|
422
424
|
};
|
|
423
425
|
|
|
424
426
|
cache?: {
|
|
@@ -613,6 +615,30 @@ API Client: Reads x-locale header → Appends ?lang=tr
|
|
|
613
615
|
Backend: GET /api/posts?lang=tr
|
|
614
616
|
```
|
|
615
617
|
|
|
618
|
+
### Route Matching with Locale Prefix
|
|
619
|
+
|
|
620
|
+
When using `localePrefix: 'always'` (e.g., with next-intl), the library automatically strips the locale prefix before matching routes:
|
|
621
|
+
|
|
622
|
+
```ts
|
|
623
|
+
createAuthProxy({
|
|
624
|
+
// ...
|
|
625
|
+
access: {
|
|
626
|
+
protectedRoutes: ['/dashboard', '/profile'],
|
|
627
|
+
authRoutes: ['/login', '/register'],
|
|
628
|
+
},
|
|
629
|
+
i18n: {
|
|
630
|
+
enabled: true,
|
|
631
|
+
locales: ['en', 'tr'],
|
|
632
|
+
defaultLocale: 'en',
|
|
633
|
+
},
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
// These all match correctly:
|
|
637
|
+
// /login → matches authRoutes '/login'
|
|
638
|
+
// /tr/login → matches authRoutes '/login' (locale stripped)
|
|
639
|
+
// /en/dashboard → matches protectedRoutes '/dashboard' (locale stripped)
|
|
640
|
+
```
|
|
641
|
+
|
|
616
642
|
### With next-intl
|
|
617
643
|
|
|
618
644
|
The easiest way to integrate with next-intl is using the `middleware` option:
|
|
@@ -703,6 +729,24 @@ React context provider for client-side auth state.
|
|
|
703
729
|
</AuthProvider>
|
|
704
730
|
```
|
|
705
731
|
|
|
732
|
+
#### Custom Auth Response Parsing
|
|
733
|
+
|
|
734
|
+
For backends with non-standard auth response formats, use `parseAuthResponse`:
|
|
735
|
+
|
|
736
|
+
```tsx
|
|
737
|
+
<AuthProvider
|
|
738
|
+
// Standard props...
|
|
739
|
+
parseAuthResponse={(json) => ({
|
|
740
|
+
success: json.ok === true, // Your success field
|
|
741
|
+
message: json.msg, // Your message field
|
|
742
|
+
user: json.result?.user, // User data (optional)
|
|
743
|
+
errors: json.validation_errors, // Error details (optional)
|
|
744
|
+
})}
|
|
745
|
+
>
|
|
746
|
+
{children}
|
|
747
|
+
</AuthProvider>
|
|
748
|
+
```
|
|
749
|
+
|
|
706
750
|
### useAuth()
|
|
707
751
|
|
|
708
752
|
Hook to access authentication state.
|
package/dist/client.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var react=require('react'),
|
|
2
|
+
'use strict';var react=require('react'),E=require('swr'),jsxRuntime=require('react/jsx-runtime'),navigation=require('next/navigation');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var E__default=/*#__PURE__*/_interopDefault(E);var w=react.createContext(void 0);function F(r){if(!r||typeof r!="object")return null;let e=r;return e.success&&e.data?e.data:e.user?e.user:"id"in e||"email"in e||"name"in e||"type"in e?e:null}function G(r){if(!r||typeof r!="object")return false;let e=r;return e.token_type==="guest"||e.type==="guest"}function q({children:r,initialUser:e,userEndpoint:f="/api/auth/me",loginEndpoint:o="/api/auth/login",registerEndpoint:m="/api/auth/register",logoutEndpoint:x="/api/auth/logout",logoutRedirect:U,isGuestFn:k=G,parseResponse:l=F,parseAuthResponse:d,swrConfig:b={},onLogin:h,onLogout:D,onError:c}){let V=react.useCallback(async n=>{let s=await fetch(n);if(!s.ok){if(s.status===401)return null;throw new Error("Failed to fetch user")}let a=await s.json();return l(a)},[l]),{data:g,error:P,isLoading:C,mutate:u}=E__default.default(f,V,{fallbackData:e??void 0,revalidateOnFocus:true,revalidateOnReconnect:true,revalidateOnMount:!e,refreshInterval:0,shouldRetryOnError:false,...b,onError:n=>{c?.(n);}}),R=react.useCallback(async n=>{try{let s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await s.json();if(d){let t=d(a);return t.success?(t.user?(await u(t.user,!1),h?.(t.user)):await u(),{success:!0,user:t.user??void 0,message:t.message}):{success:!1,message:t.message||"Login failed",errors:t.errors}}let i=a;if(s.ok&&i.success!==!1){let t=l(a);return t?(await u(t,!1),h?.(t)):await u(),{success:!0,user:t??void 0,message:i.message}}return {success:!1,message:i.message||"Login failed",errors:i.errors}}catch(s){let a=s instanceof Error?s:new Error("Login failed");return c?.(a),{success:false,message:a.message}}},[o,u,h,c,l,d]),v=react.useCallback(async n=>{try{let s=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await s.json();if(d){let t=d(a);return t.success?(t.user?(await u(t.user,!1),h?.(t.user)):await u(),{success:!0,user:t.user??void 0,message:t.message}):{success:!1,message:t.message||"Registration failed",errors:t.errors}}let i=a;if(s.ok&&i.success!==!1){let t=l(a);return t?(await u(t,!1),h?.(t)):await u(),{success:!0,user:t??void 0,message:i.message}}return {success:!1,message:i.message||"Registration failed",errors:i.errors}}catch(s){let a=s instanceof Error?s:new Error("Registration failed");return c?.(a),{success:false,message:a.message}}},[m,u,h,c,l,d]),O=react.useCallback(async()=>{try{await fetch(x,{method:"POST"}),await u(null,!1),D?.(),U&&typeof window<"u"&&(window.location.href=U);}catch(n){let s=n instanceof Error?n:new Error("Logout failed");throw c?.(s),s}},[x,U,u,D,c]),y=react.useCallback(async()=>{await u();},[u]),T=k(g??null),j=!!g&&!T,I=react.useMemo(()=>({user:g??null,isLoading:C,isAuthenticated:j,isGuest:T,error:P??null,login:R,register:v,logout:O,refresh:y,mutate:y}),[g,C,j,T,P,R,v,O,y]);return jsxRuntime.jsx(w.Provider,{value:I,children:r})}function A(r={}){let e=react.useContext(w),f=navigation.useRouter();if(!e)throw new Error("useAuth must be used within an AuthProvider. Wrap your app with <AuthProvider> from next-api-layer/client");let{redirectTo:o,redirectIfFound:m}=r;return e.isLoading||(o&&!e.isAuthenticated&&!e.isGuest&&typeof window<"u"&&f.replace(o),m&&e.isAuthenticated&&typeof window<"u"&&f.replace(m)),e}function W(){let{user:r,isLoading:e,isAuthenticated:f,isGuest:o}=A();return {user:r,isLoading:e,isAuthenticated:f,isGuest:o}}function _(r="/login"){let e=A({redirectTo:r});if(!e.isLoading&&!e.isAuthenticated)throw new Error("Authentication required");return e}function z(r="/"){return A({redirectIfFound:r})}exports.AuthContext=w;exports.AuthProvider=q;exports.useAuth=A;exports.useRedirectIfAuth=z;exports.useRequireAuth=_;exports.useUser=W;//# sourceMappingURL=client.cjs.map
|
|
3
3
|
//# sourceMappingURL=client.cjs.map
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/AuthProvider.tsx","../src/client/useAuth.ts"],"names":["AuthContext","createContext","defaultParseResponse","response","res","defaultIsGuest","user","u","AuthProvider","children","initialUser","userEndpoint","loginEndpoint","registerEndpoint","logoutEndpoint","logoutRedirect","isGuestFn","parseResponse","swrConfig","onLogin","onLogout","onError","fetcher","useCallback","url","json","error","isLoading","mutate","useSWR","err","login","credentials","userData","errorResponse","register","data","logout","refresh","isGuest","isAuthenticated","contextValue","useMemo","jsx","useAuth","options","context","useContext","router","useRouter","redirectTo","redirectIfFound","useUser","useRequireAuth","auth","useRedirectIfAuth"],"mappings":"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","file":"client.cjs","sourcesContent":["'use client';\r\n\r\n/**\r\n * AuthProvider - Generic React context for any backend format\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * <AuthProvider>\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n * \r\n * @example With custom user type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; email: string; };\r\n * }\r\n * \r\n * <AuthProvider<MyUser>\r\n * initialUser={serverUser}\r\n * isGuestFn={(u) => u?.type === 'guest'}\r\n * parseResponse={(res) => res.data}\r\n * >\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n */\r\n\r\nimport React, { createContext, useCallback, useMemo } from 'react';\r\nimport useSWR from 'swr';\r\nimport type { \r\n AuthContextValue, \r\n AuthProviderProps, \r\n LoginCredentials,\r\n RegisterData,\r\n AuthResult,\r\n DefaultUserData,\r\n ApiResponse,\r\n} from './types';\r\n\r\n// ==================== Context ====================\r\n\r\n// We use 'any' here because the context needs to work with any user type\r\n// The actual type safety comes from useAuth<TUser>() hook\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport const AuthContext = createContext<AuthContextValue<any> | undefined>(undefined);\r\n\r\n// ==================== Default Functions ====================\r\n\r\n/** Default response parser - handles common API formats */\r\nfunction defaultParseResponse<TUser>(response: unknown): TUser | null {\r\n if (!response || typeof response !== 'object') return null;\r\n \r\n const res = response as Record<string, unknown>;\r\n \r\n // Format: { success: true, data: user }\r\n if (res.success && res.data) {\r\n return res.data as TUser;\r\n }\r\n \r\n // Format: { user: {...} }\r\n if (res.user) {\r\n return res.user as TUser;\r\n }\r\n \r\n // Format: user object directly\r\n if ('id' in res || 'email' in res || 'name' in res || 'type' in res) {\r\n return res as TUser;\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/** Default guest check - handles common patterns */\r\nfunction defaultIsGuest<TUser>(user: TUser | null): boolean {\r\n if (!user || typeof user !== 'object') return false;\r\n \r\n const u = user as Record<string, unknown>;\r\n \r\n // Check token_type (flat structure)\r\n if (u.token_type === 'guest') return true;\r\n \r\n // Check type (nested structure)\r\n if (u.type === 'guest') return true;\r\n \r\n return false;\r\n}\r\n\r\n// ==================== Provider Component ====================\r\n\r\nexport function AuthProvider<TUser = DefaultUserData>({\r\n children,\r\n initialUser,\r\n userEndpoint = '/api/auth/me',\r\n loginEndpoint = '/api/auth/login',\r\n registerEndpoint = '/api/auth/register',\r\n logoutEndpoint = '/api/auth/logout',\r\n logoutRedirect,\r\n isGuestFn = defaultIsGuest,\r\n parseResponse = defaultParseResponse,\r\n swrConfig = {},\r\n onLogin,\r\n onLogout,\r\n onError,\r\n}: AuthProviderProps<TUser>): React.ReactElement {\r\n \r\n // Create fetcher with custom parser\r\n const fetcher = useCallback(async (url: string): Promise<TUser | null> => {\r\n const res = await fetch(url);\r\n \r\n if (!res.ok) {\r\n if (res.status === 401) {\r\n return null;\r\n }\r\n throw new Error('Failed to fetch user');\r\n }\r\n \r\n const json = await res.json();\r\n return parseResponse(json);\r\n }, [parseResponse]);\r\n\r\n // Fetch user data with SWR\r\n const {\r\n data: user,\r\n error,\r\n isLoading,\r\n mutate,\r\n } = useSWR<TUser | null>(\r\n userEndpoint,\r\n fetcher,\r\n {\r\n fallbackData: initialUser ?? undefined,\r\n revalidateOnFocus: true,\r\n revalidateOnReconnect: true,\r\n revalidateOnMount: !initialUser,\r\n refreshInterval: 0,\r\n shouldRetryOnError: false,\r\n ...swrConfig,\r\n onError: (err: Error) => {\r\n onError?.(err);\r\n },\r\n }\r\n );\r\n\r\n // Login function\r\n const login = useCallback(async (credentials: LoginCredentials): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(loginEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(credentials),\r\n });\r\n\r\n const json = await res.json();\r\n const userData = parseResponse(json);\r\n\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n return { success: true, user: userData };\r\n }\r\n\r\n const errorResponse = json as ApiResponse;\r\n return {\r\n success: false,\r\n message: errorResponse.message || 'Login failed',\r\n errors: errorResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Login failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [loginEndpoint, mutate, onLogin, onError, parseResponse]);\r\n\r\n // Register function\r\n const register = useCallback(async (data: RegisterData): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(registerEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(data),\r\n });\r\n\r\n const json = await res.json();\r\n const userData = parseResponse(json);\r\n\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n return { success: true, user: userData };\r\n }\r\n\r\n const errorResponse = json as ApiResponse;\r\n return {\r\n success: false,\r\n message: errorResponse.message || 'Registration failed',\r\n errors: errorResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Registration failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [registerEndpoint, mutate, onLogin, onError, parseResponse]);\r\n\r\n // Logout function\r\n const logout = useCallback(async (): Promise<void> => {\r\n try {\r\n await fetch(logoutEndpoint, { method: 'POST' });\r\n await mutate(null, false);\r\n onLogout?.();\r\n \r\n // Redirect after logout if configured\r\n if (logoutRedirect && typeof window !== 'undefined') {\r\n window.location.href = logoutRedirect;\r\n }\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Logout failed');\r\n onError?.(error);\r\n throw error;\r\n }\r\n }, [logoutEndpoint, logoutRedirect, mutate, onLogout, onError]);\r\n\r\n // Refresh user data\r\n const refresh = useCallback(async (): Promise<void> => {\r\n await mutate();\r\n }, [mutate]);\r\n\r\n // Compute derived state using custom isGuestFn\r\n const isGuest = isGuestFn(user ?? null);\r\n const isAuthenticated = !!user && !isGuest;\r\n\r\n // Memoize context value\r\n const contextValue = useMemo<AuthContextValue<TUser>>(() => ({\r\n user: user ?? null,\r\n isLoading,\r\n isAuthenticated,\r\n isGuest,\r\n error: error ?? null,\r\n login,\r\n register,\r\n logout,\r\n refresh,\r\n mutate: refresh,\r\n }), [user, isLoading, isAuthenticated, isGuest, error, login, register, logout, refresh]);\r\n\r\n return (\r\n <AuthContext.Provider value={contextValue}>\r\n {children}\r\n </AuthContext.Provider>\r\n );\r\n}\r\n","'use client';\r\n\r\n/**\r\n * useAuth Hook - Generic for any user type\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * const { user, isAuthenticated, logout } = useAuth();\r\n * ```\r\n * \r\n * @example With custom type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; };\r\n * }\r\n * \r\n * const { user } = useAuth<MyUser>();\r\n * // user is MyUser | null\r\n * ```\r\n */\r\n\r\nimport { useContext } from 'react';\r\nimport { useRouter } from 'next/navigation';\r\nimport { AuthContext } from './AuthProvider';\r\nimport type { AuthContextValue, UseAuthOptions, DefaultUserData } from './types';\r\n\r\n/**\r\n * Hook to access authentication state and methods\r\n * \r\n * @typeParam TUser - User data type (defaults to DefaultUserData)\r\n */\r\nexport function useAuth<TUser = DefaultUserData>(\r\n options: UseAuthOptions = {}\r\n): AuthContextValue<TUser> {\r\n const context = useContext(AuthContext) as AuthContextValue<TUser> | undefined;\r\n const router = useRouter();\r\n\r\n if (!context) {\r\n throw new Error(\r\n 'useAuth must be used within an AuthProvider. ' +\r\n 'Wrap your app with <AuthProvider> from next-api-layer/client'\r\n );\r\n }\r\n\r\n const { redirectTo, redirectIfFound } = options;\r\n\r\n // Handle redirects based on auth state\r\n if (!context.isLoading) {\r\n if (redirectTo && !context.isAuthenticated && !context.isGuest) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectTo);\r\n }\r\n }\r\n\r\n if (redirectIfFound && context.isAuthenticated) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectIfFound);\r\n }\r\n }\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * Hook to get only the user object\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useUser<TUser = DefaultUserData>() {\r\n const { user, isLoading, isAuthenticated, isGuest } = useAuth<TUser>();\r\n return { user, isLoading, isAuthenticated, isGuest };\r\n}\r\n\r\n/**\r\n * Hook for protected pages - redirects if not authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRequireAuth<TUser = DefaultUserData>(redirectTo = '/login') {\r\n const auth = useAuth<TUser>({ redirectTo });\r\n \r\n if (!auth.isLoading && !auth.isAuthenticated) {\r\n throw new Error('Authentication required');\r\n }\r\n \r\n return auth;\r\n}\r\n\r\n/**\r\n * Hook for auth pages - redirects if already authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRedirectIfAuth<TUser = DefaultUserData>(redirectTo = '/') {\r\n return useAuth<TUser>({ redirectIfFound: redirectTo });\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/AuthProvider.tsx","../src/client/useAuth.ts"],"names":["AuthContext","createContext","defaultParseResponse","response","res","defaultIsGuest","user","u","AuthProvider","children","initialUser","userEndpoint","loginEndpoint","registerEndpoint","logoutEndpoint","logoutRedirect","isGuestFn","parseResponse","parseAuthResponse","swrConfig","onLogin","onLogout","onError","fetcher","useCallback","url","json","error","isLoading","mutate","useSWR","err","login","credentials","parsed","apiResponse","userData","register","data","logout","refresh","isGuest","isAuthenticated","contextValue","useMemo","jsx","useAuth","options","context","useContext","router","useRouter","redirectTo","redirectIfFound","useUser","useRequireAuth","auth","useRedirectIfAuth"],"mappings":"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","file":"client.cjs","sourcesContent":["'use client';\r\n\r\n/**\r\n * AuthProvider - Generic React context for any backend format\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * <AuthProvider>\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n * \r\n * @example With custom user type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; email: string; };\r\n * }\r\n * \r\n * <AuthProvider<MyUser>\r\n * initialUser={serverUser}\r\n * isGuestFn={(u) => u?.type === 'guest'}\r\n * parseResponse={(res) => res.data}\r\n * >\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n */\r\n\r\nimport React, { createContext, useCallback, useMemo } from 'react';\r\nimport useSWR from 'swr';\r\nimport type { \r\n AuthContextValue, \r\n AuthProviderProps, \r\n LoginCredentials,\r\n RegisterData,\r\n AuthResult,\r\n DefaultUserData,\r\n ApiResponse,\r\n} from './types';\r\n\r\n// ==================== Context ====================\r\n\r\n// We use 'any' here because the context needs to work with any user type\r\n// The actual type safety comes from useAuth<TUser>() hook\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport const AuthContext = createContext<AuthContextValue<any> | undefined>(undefined);\r\n\r\n// ==================== Default Functions ====================\r\n\r\n/** Default response parser - handles common API formats */\r\nfunction defaultParseResponse<TUser>(response: unknown): TUser | null {\r\n if (!response || typeof response !== 'object') return null;\r\n \r\n const res = response as Record<string, unknown>;\r\n \r\n // Format: { success: true, data: user }\r\n if (res.success && res.data) {\r\n return res.data as TUser;\r\n }\r\n \r\n // Format: { user: {...} }\r\n if (res.user) {\r\n return res.user as TUser;\r\n }\r\n \r\n // Format: user object directly\r\n if ('id' in res || 'email' in res || 'name' in res || 'type' in res) {\r\n return res as TUser;\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/** Default guest check - handles common patterns */\r\nfunction defaultIsGuest<TUser>(user: TUser | null): boolean {\r\n if (!user || typeof user !== 'object') return false;\r\n \r\n const u = user as Record<string, unknown>;\r\n \r\n // Check token_type (flat structure)\r\n if (u.token_type === 'guest') return true;\r\n \r\n // Check type (nested structure)\r\n if (u.type === 'guest') return true;\r\n \r\n return false;\r\n}\r\n\r\n// ==================== Provider Component ====================\r\n\r\nexport function AuthProvider<TUser = DefaultUserData>({\r\n children,\r\n initialUser,\r\n userEndpoint = '/api/auth/me',\r\n loginEndpoint = '/api/auth/login',\r\n registerEndpoint = '/api/auth/register',\r\n logoutEndpoint = '/api/auth/logout',\r\n logoutRedirect,\r\n isGuestFn = defaultIsGuest,\r\n parseResponse = defaultParseResponse,\r\n parseAuthResponse,\r\n swrConfig = {},\r\n onLogin,\r\n onLogout,\r\n onError,\r\n}: AuthProviderProps<TUser>): React.ReactElement {\r\n \r\n // Create fetcher with custom parser\r\n const fetcher = useCallback(async (url: string): Promise<TUser | null> => {\r\n const res = await fetch(url);\r\n \r\n if (!res.ok) {\r\n if (res.status === 401) {\r\n return null;\r\n }\r\n throw new Error('Failed to fetch user');\r\n }\r\n \r\n const json = await res.json();\r\n return parseResponse(json);\r\n }, [parseResponse]);\r\n\r\n // Fetch user data with SWR\r\n const {\r\n data: user,\r\n error,\r\n isLoading,\r\n mutate,\r\n } = useSWR<TUser | null>(\r\n userEndpoint,\r\n fetcher,\r\n {\r\n fallbackData: initialUser ?? undefined,\r\n revalidateOnFocus: true,\r\n revalidateOnReconnect: true,\r\n revalidateOnMount: !initialUser,\r\n refreshInterval: 0,\r\n shouldRetryOnError: false,\r\n ...swrConfig,\r\n onError: (err: Error) => {\r\n onError?.(err);\r\n },\r\n }\r\n );\r\n\r\n // Login function\r\n const login = useCallback(async (credentials: LoginCredentials): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(loginEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(credentials),\r\n });\r\n\r\n const json = await res.json();\r\n\r\n // Use custom parser if provided\r\n if (parseAuthResponse) {\r\n const parsed = parseAuthResponse(json);\r\n if (parsed.success) {\r\n if (parsed.user) {\r\n await mutate(parsed.user, false);\r\n onLogin?.(parsed.user);\r\n } else {\r\n // No user data, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: parsed.user ?? undefined, message: parsed.message };\r\n }\r\n return {\r\n success: false,\r\n message: parsed.message || 'Login failed',\r\n errors: parsed.errors,\r\n };\r\n }\r\n\r\n // Default behavior: check res.ok and json.success\r\n const apiResponse = json as ApiResponse;\r\n if (res.ok && apiResponse.success !== false) {\r\n // Try to extract user data using parseResponse\r\n const userData = parseResponse(json);\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n } else {\r\n // No user data in response, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: userData ?? undefined, message: apiResponse.message };\r\n }\r\n\r\n return {\r\n success: false,\r\n message: apiResponse.message || 'Login failed',\r\n errors: apiResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Login failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [loginEndpoint, mutate, onLogin, onError, parseResponse, parseAuthResponse]);\r\n\r\n // Register function\r\n const register = useCallback(async (data: RegisterData): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(registerEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(data),\r\n });\r\n\r\n const json = await res.json();\r\n\r\n // Use custom parser if provided\r\n if (parseAuthResponse) {\r\n const parsed = parseAuthResponse(json);\r\n if (parsed.success) {\r\n if (parsed.user) {\r\n await mutate(parsed.user, false);\r\n onLogin?.(parsed.user);\r\n } else {\r\n // No user data, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: parsed.user ?? undefined, message: parsed.message };\r\n }\r\n return {\r\n success: false,\r\n message: parsed.message || 'Registration failed',\r\n errors: parsed.errors,\r\n };\r\n }\r\n\r\n // Default behavior: check res.ok and json.success\r\n const apiResponse = json as ApiResponse;\r\n if (res.ok && apiResponse.success !== false) {\r\n // Try to extract user data using parseResponse\r\n const userData = parseResponse(json);\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n } else {\r\n // No user data in response, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: userData ?? undefined, message: apiResponse.message };\r\n }\r\n\r\n return {\r\n success: false,\r\n message: apiResponse.message || 'Registration failed',\r\n errors: apiResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Registration failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [registerEndpoint, mutate, onLogin, onError, parseResponse, parseAuthResponse]);\r\n\r\n // Logout function\r\n const logout = useCallback(async (): Promise<void> => {\r\n try {\r\n await fetch(logoutEndpoint, { method: 'POST' });\r\n await mutate(null, false);\r\n onLogout?.();\r\n \r\n // Redirect after logout if configured\r\n if (logoutRedirect && typeof window !== 'undefined') {\r\n window.location.href = logoutRedirect;\r\n }\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Logout failed');\r\n onError?.(error);\r\n throw error;\r\n }\r\n }, [logoutEndpoint, logoutRedirect, mutate, onLogout, onError]);\r\n\r\n // Refresh user data\r\n const refresh = useCallback(async (): Promise<void> => {\r\n await mutate();\r\n }, [mutate]);\r\n\r\n // Compute derived state using custom isGuestFn\r\n const isGuest = isGuestFn(user ?? null);\r\n const isAuthenticated = !!user && !isGuest;\r\n\r\n // Memoize context value\r\n const contextValue = useMemo<AuthContextValue<TUser>>(() => ({\r\n user: user ?? null,\r\n isLoading,\r\n isAuthenticated,\r\n isGuest,\r\n error: error ?? null,\r\n login,\r\n register,\r\n logout,\r\n refresh,\r\n mutate: refresh,\r\n }), [user, isLoading, isAuthenticated, isGuest, error, login, register, logout, refresh]);\r\n\r\n return (\r\n <AuthContext.Provider value={contextValue}>\r\n {children}\r\n </AuthContext.Provider>\r\n );\r\n}\r\n","'use client';\r\n\r\n/**\r\n * useAuth Hook - Generic for any user type\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * const { user, isAuthenticated, logout } = useAuth();\r\n * ```\r\n * \r\n * @example With custom type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; };\r\n * }\r\n * \r\n * const { user } = useAuth<MyUser>();\r\n * // user is MyUser | null\r\n * ```\r\n */\r\n\r\nimport { useContext } from 'react';\r\nimport { useRouter } from 'next/navigation';\r\nimport { AuthContext } from './AuthProvider';\r\nimport type { AuthContextValue, UseAuthOptions, DefaultUserData } from './types';\r\n\r\n/**\r\n * Hook to access authentication state and methods\r\n * \r\n * @typeParam TUser - User data type (defaults to DefaultUserData)\r\n */\r\nexport function useAuth<TUser = DefaultUserData>(\r\n options: UseAuthOptions = {}\r\n): AuthContextValue<TUser> {\r\n const context = useContext(AuthContext) as AuthContextValue<TUser> | undefined;\r\n const router = useRouter();\r\n\r\n if (!context) {\r\n throw new Error(\r\n 'useAuth must be used within an AuthProvider. ' +\r\n 'Wrap your app with <AuthProvider> from next-api-layer/client'\r\n );\r\n }\r\n\r\n const { redirectTo, redirectIfFound } = options;\r\n\r\n // Handle redirects based on auth state\r\n if (!context.isLoading) {\r\n if (redirectTo && !context.isAuthenticated && !context.isGuest) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectTo);\r\n }\r\n }\r\n\r\n if (redirectIfFound && context.isAuthenticated) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectIfFound);\r\n }\r\n }\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * Hook to get only the user object\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useUser<TUser = DefaultUserData>() {\r\n const { user, isLoading, isAuthenticated, isGuest } = useAuth<TUser>();\r\n return { user, isLoading, isAuthenticated, isGuest };\r\n}\r\n\r\n/**\r\n * Hook for protected pages - redirects if not authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRequireAuth<TUser = DefaultUserData>(redirectTo = '/login') {\r\n const auth = useAuth<TUser>({ redirectTo });\r\n \r\n if (!auth.isLoading && !auth.isAuthenticated) {\r\n throw new Error('Authentication required');\r\n }\r\n \r\n return auth;\r\n}\r\n\r\n/**\r\n * Hook for auth pages - redirects if already authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRedirectIfAuth<TUser = DefaultUserData>(redirectTo = '/') {\r\n return useAuth<TUser>({ redirectIfFound: redirectTo });\r\n}\r\n"]}
|
package/dist/client.d.cts
CHANGED
|
@@ -40,6 +40,20 @@ interface AuthResult<TUser = DefaultUserData> {
|
|
|
40
40
|
user?: TUser;
|
|
41
41
|
errors?: Record<string, unknown>;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Return type for parseAuthResponse function.
|
|
45
|
+
* Used to parse login/register responses from different backend formats.
|
|
46
|
+
*/
|
|
47
|
+
interface AuthResponseParsed<TUser = DefaultUserData> {
|
|
48
|
+
/** Whether the auth operation was successful */
|
|
49
|
+
success: boolean;
|
|
50
|
+
/** Optional message from the backend */
|
|
51
|
+
message?: string;
|
|
52
|
+
/** User data if available (optional - will be fetched from /me if not provided) */
|
|
53
|
+
user?: TUser | null;
|
|
54
|
+
/** Validation or other errors */
|
|
55
|
+
errors?: Record<string, unknown>;
|
|
56
|
+
}
|
|
43
57
|
interface AuthProviderProps<TUser = DefaultUserData> {
|
|
44
58
|
children: React.ReactNode;
|
|
45
59
|
/** Initial user data from server (SSR) */
|
|
@@ -61,9 +75,25 @@ interface AuthProviderProps<TUser = DefaultUserData> {
|
|
|
61
75
|
isGuestFn?: (user: TUser | null) => boolean;
|
|
62
76
|
/**
|
|
63
77
|
* Function to parse API response and extract user data
|
|
78
|
+
* Used for /me endpoint responses
|
|
64
79
|
* @default (response) => response.data || response.user || response
|
|
65
80
|
*/
|
|
66
81
|
parseResponse?: (response: unknown) => TUser | null;
|
|
82
|
+
/**
|
|
83
|
+
* Function to parse login/register responses.
|
|
84
|
+
* Use this when your backend has a non-standard auth response format.
|
|
85
|
+
* If not provided, uses smart default: res.ok && json.success !== false
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```tsx
|
|
89
|
+
* parseAuthResponse={(json) => ({
|
|
90
|
+
* success: json.ok === true,
|
|
91
|
+
* user: json.result?.user,
|
|
92
|
+
* message: json.message,
|
|
93
|
+
* })}
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
parseAuthResponse?: (response: unknown) => AuthResponseParsed<TUser>;
|
|
67
97
|
/** SWR config overrides */
|
|
68
98
|
swrConfig?: {
|
|
69
99
|
refreshInterval?: number;
|
|
@@ -134,7 +164,7 @@ type UserData = DefaultUserData;
|
|
|
134
164
|
*/
|
|
135
165
|
|
|
136
166
|
declare const AuthContext: React$1.Context<AuthContextValue<any> | undefined>;
|
|
137
|
-
declare function AuthProvider<TUser = DefaultUserData>({ children, initialUser, userEndpoint, loginEndpoint, registerEndpoint, logoutEndpoint, logoutRedirect, isGuestFn, parseResponse, swrConfig, onLogin, onLogout, onError, }: AuthProviderProps<TUser>): React$1.ReactElement;
|
|
167
|
+
declare function AuthProvider<TUser = DefaultUserData>({ children, initialUser, userEndpoint, loginEndpoint, registerEndpoint, logoutEndpoint, logoutRedirect, isGuestFn, parseResponse, parseAuthResponse, swrConfig, onLogin, onLogout, onError, }: AuthProviderProps<TUser>): React$1.ReactElement;
|
|
138
168
|
|
|
139
169
|
/**
|
|
140
170
|
* Hook to access authentication state and methods
|
|
@@ -166,4 +196,4 @@ declare function useRequireAuth<TUser = DefaultUserData>(redirectTo?: string): A
|
|
|
166
196
|
*/
|
|
167
197
|
declare function useRedirectIfAuth<TUser = DefaultUserData>(redirectTo?: string): AuthContextValue<TUser>;
|
|
168
198
|
|
|
169
|
-
export { type ApiResponse, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthResult, type DefaultUserData, type LoginCredentials, type RegisterData, type UseAuthOptions, type UserData, useAuth, useRedirectIfAuth, useRequireAuth, useUser };
|
|
199
|
+
export { type ApiResponse, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthResponseParsed, type AuthResult, type DefaultUserData, type LoginCredentials, type RegisterData, type UseAuthOptions, type UserData, useAuth, useRedirectIfAuth, useRequireAuth, useUser };
|
package/dist/client.d.ts
CHANGED
|
@@ -40,6 +40,20 @@ interface AuthResult<TUser = DefaultUserData> {
|
|
|
40
40
|
user?: TUser;
|
|
41
41
|
errors?: Record<string, unknown>;
|
|
42
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Return type for parseAuthResponse function.
|
|
45
|
+
* Used to parse login/register responses from different backend formats.
|
|
46
|
+
*/
|
|
47
|
+
interface AuthResponseParsed<TUser = DefaultUserData> {
|
|
48
|
+
/** Whether the auth operation was successful */
|
|
49
|
+
success: boolean;
|
|
50
|
+
/** Optional message from the backend */
|
|
51
|
+
message?: string;
|
|
52
|
+
/** User data if available (optional - will be fetched from /me if not provided) */
|
|
53
|
+
user?: TUser | null;
|
|
54
|
+
/** Validation or other errors */
|
|
55
|
+
errors?: Record<string, unknown>;
|
|
56
|
+
}
|
|
43
57
|
interface AuthProviderProps<TUser = DefaultUserData> {
|
|
44
58
|
children: React.ReactNode;
|
|
45
59
|
/** Initial user data from server (SSR) */
|
|
@@ -61,9 +75,25 @@ interface AuthProviderProps<TUser = DefaultUserData> {
|
|
|
61
75
|
isGuestFn?: (user: TUser | null) => boolean;
|
|
62
76
|
/**
|
|
63
77
|
* Function to parse API response and extract user data
|
|
78
|
+
* Used for /me endpoint responses
|
|
64
79
|
* @default (response) => response.data || response.user || response
|
|
65
80
|
*/
|
|
66
81
|
parseResponse?: (response: unknown) => TUser | null;
|
|
82
|
+
/**
|
|
83
|
+
* Function to parse login/register responses.
|
|
84
|
+
* Use this when your backend has a non-standard auth response format.
|
|
85
|
+
* If not provided, uses smart default: res.ok && json.success !== false
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```tsx
|
|
89
|
+
* parseAuthResponse={(json) => ({
|
|
90
|
+
* success: json.ok === true,
|
|
91
|
+
* user: json.result?.user,
|
|
92
|
+
* message: json.message,
|
|
93
|
+
* })}
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
parseAuthResponse?: (response: unknown) => AuthResponseParsed<TUser>;
|
|
67
97
|
/** SWR config overrides */
|
|
68
98
|
swrConfig?: {
|
|
69
99
|
refreshInterval?: number;
|
|
@@ -134,7 +164,7 @@ type UserData = DefaultUserData;
|
|
|
134
164
|
*/
|
|
135
165
|
|
|
136
166
|
declare const AuthContext: React$1.Context<AuthContextValue<any> | undefined>;
|
|
137
|
-
declare function AuthProvider<TUser = DefaultUserData>({ children, initialUser, userEndpoint, loginEndpoint, registerEndpoint, logoutEndpoint, logoutRedirect, isGuestFn, parseResponse, swrConfig, onLogin, onLogout, onError, }: AuthProviderProps<TUser>): React$1.ReactElement;
|
|
167
|
+
declare function AuthProvider<TUser = DefaultUserData>({ children, initialUser, userEndpoint, loginEndpoint, registerEndpoint, logoutEndpoint, logoutRedirect, isGuestFn, parseResponse, parseAuthResponse, swrConfig, onLogin, onLogout, onError, }: AuthProviderProps<TUser>): React$1.ReactElement;
|
|
138
168
|
|
|
139
169
|
/**
|
|
140
170
|
* Hook to access authentication state and methods
|
|
@@ -166,4 +196,4 @@ declare function useRequireAuth<TUser = DefaultUserData>(redirectTo?: string): A
|
|
|
166
196
|
*/
|
|
167
197
|
declare function useRedirectIfAuth<TUser = DefaultUserData>(redirectTo?: string): AuthContextValue<TUser>;
|
|
168
198
|
|
|
169
|
-
export { type ApiResponse, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthResult, type DefaultUserData, type LoginCredentials, type RegisterData, type UseAuthOptions, type UserData, useAuth, useRedirectIfAuth, useRequireAuth, useUser };
|
|
199
|
+
export { type ApiResponse, AuthContext, type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthResponseParsed, type AuthResult, type DefaultUserData, type LoginCredentials, type RegisterData, type UseAuthOptions, type UserData, useAuth, useRedirectIfAuth, useRequireAuth, useUser };
|
package/dist/client.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {createContext,useCallback,useMemo,useContext}from'react';import
|
|
2
|
+
import {createContext,useCallback,useMemo,useContext}from'react';import E from'swr';import {jsx}from'react/jsx-runtime';import {useRouter}from'next/navigation';var w=createContext(void 0);function F(r){if(!r||typeof r!="object")return null;let e=r;return e.success&&e.data?e.data:e.user?e.user:"id"in e||"email"in e||"name"in e||"type"in e?e:null}function G(r){if(!r||typeof r!="object")return false;let e=r;return e.token_type==="guest"||e.type==="guest"}function q({children:r,initialUser:e,userEndpoint:f="/api/auth/me",loginEndpoint:o="/api/auth/login",registerEndpoint:m="/api/auth/register",logoutEndpoint:x="/api/auth/logout",logoutRedirect:U,isGuestFn:k=G,parseResponse:l=F,parseAuthResponse:d,swrConfig:b={},onLogin:h,onLogout:D,onError:c}){let V=useCallback(async n=>{let s=await fetch(n);if(!s.ok){if(s.status===401)return null;throw new Error("Failed to fetch user")}let a=await s.json();return l(a)},[l]),{data:g,error:P,isLoading:C,mutate:u}=E(f,V,{fallbackData:e??void 0,revalidateOnFocus:true,revalidateOnReconnect:true,revalidateOnMount:!e,refreshInterval:0,shouldRetryOnError:false,...b,onError:n=>{c?.(n);}}),R=useCallback(async n=>{try{let s=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await s.json();if(d){let t=d(a);return t.success?(t.user?(await u(t.user,!1),h?.(t.user)):await u(),{success:!0,user:t.user??void 0,message:t.message}):{success:!1,message:t.message||"Login failed",errors:t.errors}}let i=a;if(s.ok&&i.success!==!1){let t=l(a);return t?(await u(t,!1),h?.(t)):await u(),{success:!0,user:t??void 0,message:i.message}}return {success:!1,message:i.message||"Login failed",errors:i.errors}}catch(s){let a=s instanceof Error?s:new Error("Login failed");return c?.(a),{success:false,message:a.message}}},[o,u,h,c,l,d]),v=useCallback(async n=>{try{let s=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)}),a=await s.json();if(d){let t=d(a);return t.success?(t.user?(await u(t.user,!1),h?.(t.user)):await u(),{success:!0,user:t.user??void 0,message:t.message}):{success:!1,message:t.message||"Registration failed",errors:t.errors}}let i=a;if(s.ok&&i.success!==!1){let t=l(a);return t?(await u(t,!1),h?.(t)):await u(),{success:!0,user:t??void 0,message:i.message}}return {success:!1,message:i.message||"Registration failed",errors:i.errors}}catch(s){let a=s instanceof Error?s:new Error("Registration failed");return c?.(a),{success:false,message:a.message}}},[m,u,h,c,l,d]),O=useCallback(async()=>{try{await fetch(x,{method:"POST"}),await u(null,!1),D?.(),U&&typeof window<"u"&&(window.location.href=U);}catch(n){let s=n instanceof Error?n:new Error("Logout failed");throw c?.(s),s}},[x,U,u,D,c]),y=useCallback(async()=>{await u();},[u]),T=k(g??null),j=!!g&&!T,I=useMemo(()=>({user:g??null,isLoading:C,isAuthenticated:j,isGuest:T,error:P??null,login:R,register:v,logout:O,refresh:y,mutate:y}),[g,C,j,T,P,R,v,O,y]);return jsx(w.Provider,{value:I,children:r})}function A(r={}){let e=useContext(w),f=useRouter();if(!e)throw new Error("useAuth must be used within an AuthProvider. Wrap your app with <AuthProvider> from next-api-layer/client");let{redirectTo:o,redirectIfFound:m}=r;return e.isLoading||(o&&!e.isAuthenticated&&!e.isGuest&&typeof window<"u"&&f.replace(o),m&&e.isAuthenticated&&typeof window<"u"&&f.replace(m)),e}function W(){let{user:r,isLoading:e,isAuthenticated:f,isGuest:o}=A();return {user:r,isLoading:e,isAuthenticated:f,isGuest:o}}function _(r="/login"){let e=A({redirectTo:r});if(!e.isLoading&&!e.isAuthenticated)throw new Error("Authentication required");return e}function z(r="/"){return A({redirectIfFound:r})}export{w as AuthContext,q as AuthProvider,A as useAuth,z as useRedirectIfAuth,_ as useRequireAuth,W as useUser};//# sourceMappingURL=client.js.map
|
|
3
3
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/AuthProvider.tsx","../src/client/useAuth.ts"],"names":["AuthContext","createContext","defaultParseResponse","response","res","defaultIsGuest","user","u","AuthProvider","children","initialUser","userEndpoint","loginEndpoint","registerEndpoint","logoutEndpoint","logoutRedirect","isGuestFn","parseResponse","swrConfig","onLogin","onLogout","onError","fetcher","useCallback","url","json","error","isLoading","mutate","useSWR","err","login","credentials","userData","errorResponse","register","data","logout","refresh","isGuest","isAuthenticated","contextValue","useMemo","jsx","useAuth","options","context","useContext","router","useRouter","redirectTo","redirectIfFound","useUser","useRequireAuth","auth","useRedirectIfAuth"],"mappings":"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","file":"client.js","sourcesContent":["'use client';\r\n\r\n/**\r\n * AuthProvider - Generic React context for any backend format\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * <AuthProvider>\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n * \r\n * @example With custom user type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; email: string; };\r\n * }\r\n * \r\n * <AuthProvider<MyUser>\r\n * initialUser={serverUser}\r\n * isGuestFn={(u) => u?.type === 'guest'}\r\n * parseResponse={(res) => res.data}\r\n * >\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n */\r\n\r\nimport React, { createContext, useCallback, useMemo } from 'react';\r\nimport useSWR from 'swr';\r\nimport type { \r\n AuthContextValue, \r\n AuthProviderProps, \r\n LoginCredentials,\r\n RegisterData,\r\n AuthResult,\r\n DefaultUserData,\r\n ApiResponse,\r\n} from './types';\r\n\r\n// ==================== Context ====================\r\n\r\n// We use 'any' here because the context needs to work with any user type\r\n// The actual type safety comes from useAuth<TUser>() hook\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport const AuthContext = createContext<AuthContextValue<any> | undefined>(undefined);\r\n\r\n// ==================== Default Functions ====================\r\n\r\n/** Default response parser - handles common API formats */\r\nfunction defaultParseResponse<TUser>(response: unknown): TUser | null {\r\n if (!response || typeof response !== 'object') return null;\r\n \r\n const res = response as Record<string, unknown>;\r\n \r\n // Format: { success: true, data: user }\r\n if (res.success && res.data) {\r\n return res.data as TUser;\r\n }\r\n \r\n // Format: { user: {...} }\r\n if (res.user) {\r\n return res.user as TUser;\r\n }\r\n \r\n // Format: user object directly\r\n if ('id' in res || 'email' in res || 'name' in res || 'type' in res) {\r\n return res as TUser;\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/** Default guest check - handles common patterns */\r\nfunction defaultIsGuest<TUser>(user: TUser | null): boolean {\r\n if (!user || typeof user !== 'object') return false;\r\n \r\n const u = user as Record<string, unknown>;\r\n \r\n // Check token_type (flat structure)\r\n if (u.token_type === 'guest') return true;\r\n \r\n // Check type (nested structure)\r\n if (u.type === 'guest') return true;\r\n \r\n return false;\r\n}\r\n\r\n// ==================== Provider Component ====================\r\n\r\nexport function AuthProvider<TUser = DefaultUserData>({\r\n children,\r\n initialUser,\r\n userEndpoint = '/api/auth/me',\r\n loginEndpoint = '/api/auth/login',\r\n registerEndpoint = '/api/auth/register',\r\n logoutEndpoint = '/api/auth/logout',\r\n logoutRedirect,\r\n isGuestFn = defaultIsGuest,\r\n parseResponse = defaultParseResponse,\r\n swrConfig = {},\r\n onLogin,\r\n onLogout,\r\n onError,\r\n}: AuthProviderProps<TUser>): React.ReactElement {\r\n \r\n // Create fetcher with custom parser\r\n const fetcher = useCallback(async (url: string): Promise<TUser | null> => {\r\n const res = await fetch(url);\r\n \r\n if (!res.ok) {\r\n if (res.status === 401) {\r\n return null;\r\n }\r\n throw new Error('Failed to fetch user');\r\n }\r\n \r\n const json = await res.json();\r\n return parseResponse(json);\r\n }, [parseResponse]);\r\n\r\n // Fetch user data with SWR\r\n const {\r\n data: user,\r\n error,\r\n isLoading,\r\n mutate,\r\n } = useSWR<TUser | null>(\r\n userEndpoint,\r\n fetcher,\r\n {\r\n fallbackData: initialUser ?? undefined,\r\n revalidateOnFocus: true,\r\n revalidateOnReconnect: true,\r\n revalidateOnMount: !initialUser,\r\n refreshInterval: 0,\r\n shouldRetryOnError: false,\r\n ...swrConfig,\r\n onError: (err: Error) => {\r\n onError?.(err);\r\n },\r\n }\r\n );\r\n\r\n // Login function\r\n const login = useCallback(async (credentials: LoginCredentials): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(loginEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(credentials),\r\n });\r\n\r\n const json = await res.json();\r\n const userData = parseResponse(json);\r\n\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n return { success: true, user: userData };\r\n }\r\n\r\n const errorResponse = json as ApiResponse;\r\n return {\r\n success: false,\r\n message: errorResponse.message || 'Login failed',\r\n errors: errorResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Login failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [loginEndpoint, mutate, onLogin, onError, parseResponse]);\r\n\r\n // Register function\r\n const register = useCallback(async (data: RegisterData): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(registerEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(data),\r\n });\r\n\r\n const json = await res.json();\r\n const userData = parseResponse(json);\r\n\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n return { success: true, user: userData };\r\n }\r\n\r\n const errorResponse = json as ApiResponse;\r\n return {\r\n success: false,\r\n message: errorResponse.message || 'Registration failed',\r\n errors: errorResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Registration failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [registerEndpoint, mutate, onLogin, onError, parseResponse]);\r\n\r\n // Logout function\r\n const logout = useCallback(async (): Promise<void> => {\r\n try {\r\n await fetch(logoutEndpoint, { method: 'POST' });\r\n await mutate(null, false);\r\n onLogout?.();\r\n \r\n // Redirect after logout if configured\r\n if (logoutRedirect && typeof window !== 'undefined') {\r\n window.location.href = logoutRedirect;\r\n }\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Logout failed');\r\n onError?.(error);\r\n throw error;\r\n }\r\n }, [logoutEndpoint, logoutRedirect, mutate, onLogout, onError]);\r\n\r\n // Refresh user data\r\n const refresh = useCallback(async (): Promise<void> => {\r\n await mutate();\r\n }, [mutate]);\r\n\r\n // Compute derived state using custom isGuestFn\r\n const isGuest = isGuestFn(user ?? null);\r\n const isAuthenticated = !!user && !isGuest;\r\n\r\n // Memoize context value\r\n const contextValue = useMemo<AuthContextValue<TUser>>(() => ({\r\n user: user ?? null,\r\n isLoading,\r\n isAuthenticated,\r\n isGuest,\r\n error: error ?? null,\r\n login,\r\n register,\r\n logout,\r\n refresh,\r\n mutate: refresh,\r\n }), [user, isLoading, isAuthenticated, isGuest, error, login, register, logout, refresh]);\r\n\r\n return (\r\n <AuthContext.Provider value={contextValue}>\r\n {children}\r\n </AuthContext.Provider>\r\n );\r\n}\r\n","'use client';\r\n\r\n/**\r\n * useAuth Hook - Generic for any user type\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * const { user, isAuthenticated, logout } = useAuth();\r\n * ```\r\n * \r\n * @example With custom type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; };\r\n * }\r\n * \r\n * const { user } = useAuth<MyUser>();\r\n * // user is MyUser | null\r\n * ```\r\n */\r\n\r\nimport { useContext } from 'react';\r\nimport { useRouter } from 'next/navigation';\r\nimport { AuthContext } from './AuthProvider';\r\nimport type { AuthContextValue, UseAuthOptions, DefaultUserData } from './types';\r\n\r\n/**\r\n * Hook to access authentication state and methods\r\n * \r\n * @typeParam TUser - User data type (defaults to DefaultUserData)\r\n */\r\nexport function useAuth<TUser = DefaultUserData>(\r\n options: UseAuthOptions = {}\r\n): AuthContextValue<TUser> {\r\n const context = useContext(AuthContext) as AuthContextValue<TUser> | undefined;\r\n const router = useRouter();\r\n\r\n if (!context) {\r\n throw new Error(\r\n 'useAuth must be used within an AuthProvider. ' +\r\n 'Wrap your app with <AuthProvider> from next-api-layer/client'\r\n );\r\n }\r\n\r\n const { redirectTo, redirectIfFound } = options;\r\n\r\n // Handle redirects based on auth state\r\n if (!context.isLoading) {\r\n if (redirectTo && !context.isAuthenticated && !context.isGuest) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectTo);\r\n }\r\n }\r\n\r\n if (redirectIfFound && context.isAuthenticated) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectIfFound);\r\n }\r\n }\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * Hook to get only the user object\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useUser<TUser = DefaultUserData>() {\r\n const { user, isLoading, isAuthenticated, isGuest } = useAuth<TUser>();\r\n return { user, isLoading, isAuthenticated, isGuest };\r\n}\r\n\r\n/**\r\n * Hook for protected pages - redirects if not authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRequireAuth<TUser = DefaultUserData>(redirectTo = '/login') {\r\n const auth = useAuth<TUser>({ redirectTo });\r\n \r\n if (!auth.isLoading && !auth.isAuthenticated) {\r\n throw new Error('Authentication required');\r\n }\r\n \r\n return auth;\r\n}\r\n\r\n/**\r\n * Hook for auth pages - redirects if already authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRedirectIfAuth<TUser = DefaultUserData>(redirectTo = '/') {\r\n return useAuth<TUser>({ redirectIfFound: redirectTo });\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/AuthProvider.tsx","../src/client/useAuth.ts"],"names":["AuthContext","createContext","defaultParseResponse","response","res","defaultIsGuest","user","u","AuthProvider","children","initialUser","userEndpoint","loginEndpoint","registerEndpoint","logoutEndpoint","logoutRedirect","isGuestFn","parseResponse","parseAuthResponse","swrConfig","onLogin","onLogout","onError","fetcher","useCallback","url","json","error","isLoading","mutate","useSWR","err","login","credentials","parsed","apiResponse","userData","register","data","logout","refresh","isGuest","isAuthenticated","contextValue","useMemo","jsx","useAuth","options","context","useContext","router","useRouter","redirectTo","redirectIfFound","useUser","useRequireAuth","auth","useRedirectIfAuth"],"mappings":"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","file":"client.js","sourcesContent":["'use client';\r\n\r\n/**\r\n * AuthProvider - Generic React context for any backend format\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * <AuthProvider>\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n * \r\n * @example With custom user type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; email: string; };\r\n * }\r\n * \r\n * <AuthProvider<MyUser>\r\n * initialUser={serverUser}\r\n * isGuestFn={(u) => u?.type === 'guest'}\r\n * parseResponse={(res) => res.data}\r\n * >\r\n * {children}\r\n * </AuthProvider>\r\n * ```\r\n */\r\n\r\nimport React, { createContext, useCallback, useMemo } from 'react';\r\nimport useSWR from 'swr';\r\nimport type { \r\n AuthContextValue, \r\n AuthProviderProps, \r\n LoginCredentials,\r\n RegisterData,\r\n AuthResult,\r\n DefaultUserData,\r\n ApiResponse,\r\n} from './types';\r\n\r\n// ==================== Context ====================\r\n\r\n// We use 'any' here because the context needs to work with any user type\r\n// The actual type safety comes from useAuth<TUser>() hook\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport const AuthContext = createContext<AuthContextValue<any> | undefined>(undefined);\r\n\r\n// ==================== Default Functions ====================\r\n\r\n/** Default response parser - handles common API formats */\r\nfunction defaultParseResponse<TUser>(response: unknown): TUser | null {\r\n if (!response || typeof response !== 'object') return null;\r\n \r\n const res = response as Record<string, unknown>;\r\n \r\n // Format: { success: true, data: user }\r\n if (res.success && res.data) {\r\n return res.data as TUser;\r\n }\r\n \r\n // Format: { user: {...} }\r\n if (res.user) {\r\n return res.user as TUser;\r\n }\r\n \r\n // Format: user object directly\r\n if ('id' in res || 'email' in res || 'name' in res || 'type' in res) {\r\n return res as TUser;\r\n }\r\n \r\n return null;\r\n}\r\n\r\n/** Default guest check - handles common patterns */\r\nfunction defaultIsGuest<TUser>(user: TUser | null): boolean {\r\n if (!user || typeof user !== 'object') return false;\r\n \r\n const u = user as Record<string, unknown>;\r\n \r\n // Check token_type (flat structure)\r\n if (u.token_type === 'guest') return true;\r\n \r\n // Check type (nested structure)\r\n if (u.type === 'guest') return true;\r\n \r\n return false;\r\n}\r\n\r\n// ==================== Provider Component ====================\r\n\r\nexport function AuthProvider<TUser = DefaultUserData>({\r\n children,\r\n initialUser,\r\n userEndpoint = '/api/auth/me',\r\n loginEndpoint = '/api/auth/login',\r\n registerEndpoint = '/api/auth/register',\r\n logoutEndpoint = '/api/auth/logout',\r\n logoutRedirect,\r\n isGuestFn = defaultIsGuest,\r\n parseResponse = defaultParseResponse,\r\n parseAuthResponse,\r\n swrConfig = {},\r\n onLogin,\r\n onLogout,\r\n onError,\r\n}: AuthProviderProps<TUser>): React.ReactElement {\r\n \r\n // Create fetcher with custom parser\r\n const fetcher = useCallback(async (url: string): Promise<TUser | null> => {\r\n const res = await fetch(url);\r\n \r\n if (!res.ok) {\r\n if (res.status === 401) {\r\n return null;\r\n }\r\n throw new Error('Failed to fetch user');\r\n }\r\n \r\n const json = await res.json();\r\n return parseResponse(json);\r\n }, [parseResponse]);\r\n\r\n // Fetch user data with SWR\r\n const {\r\n data: user,\r\n error,\r\n isLoading,\r\n mutate,\r\n } = useSWR<TUser | null>(\r\n userEndpoint,\r\n fetcher,\r\n {\r\n fallbackData: initialUser ?? undefined,\r\n revalidateOnFocus: true,\r\n revalidateOnReconnect: true,\r\n revalidateOnMount: !initialUser,\r\n refreshInterval: 0,\r\n shouldRetryOnError: false,\r\n ...swrConfig,\r\n onError: (err: Error) => {\r\n onError?.(err);\r\n },\r\n }\r\n );\r\n\r\n // Login function\r\n const login = useCallback(async (credentials: LoginCredentials): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(loginEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(credentials),\r\n });\r\n\r\n const json = await res.json();\r\n\r\n // Use custom parser if provided\r\n if (parseAuthResponse) {\r\n const parsed = parseAuthResponse(json);\r\n if (parsed.success) {\r\n if (parsed.user) {\r\n await mutate(parsed.user, false);\r\n onLogin?.(parsed.user);\r\n } else {\r\n // No user data, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: parsed.user ?? undefined, message: parsed.message };\r\n }\r\n return {\r\n success: false,\r\n message: parsed.message || 'Login failed',\r\n errors: parsed.errors,\r\n };\r\n }\r\n\r\n // Default behavior: check res.ok and json.success\r\n const apiResponse = json as ApiResponse;\r\n if (res.ok && apiResponse.success !== false) {\r\n // Try to extract user data using parseResponse\r\n const userData = parseResponse(json);\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n } else {\r\n // No user data in response, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: userData ?? undefined, message: apiResponse.message };\r\n }\r\n\r\n return {\r\n success: false,\r\n message: apiResponse.message || 'Login failed',\r\n errors: apiResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Login failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [loginEndpoint, mutate, onLogin, onError, parseResponse, parseAuthResponse]);\r\n\r\n // Register function\r\n const register = useCallback(async (data: RegisterData): Promise<AuthResult<TUser>> => {\r\n try {\r\n const res = await fetch(registerEndpoint, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify(data),\r\n });\r\n\r\n const json = await res.json();\r\n\r\n // Use custom parser if provided\r\n if (parseAuthResponse) {\r\n const parsed = parseAuthResponse(json);\r\n if (parsed.success) {\r\n if (parsed.user) {\r\n await mutate(parsed.user, false);\r\n onLogin?.(parsed.user);\r\n } else {\r\n // No user data, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: parsed.user ?? undefined, message: parsed.message };\r\n }\r\n return {\r\n success: false,\r\n message: parsed.message || 'Registration failed',\r\n errors: parsed.errors,\r\n };\r\n }\r\n\r\n // Default behavior: check res.ok and json.success\r\n const apiResponse = json as ApiResponse;\r\n if (res.ok && apiResponse.success !== false) {\r\n // Try to extract user data using parseResponse\r\n const userData = parseResponse(json);\r\n if (userData) {\r\n await mutate(userData, false);\r\n onLogin?.(userData);\r\n } else {\r\n // No user data in response, revalidate from /me endpoint\r\n await mutate();\r\n }\r\n return { success: true, user: userData ?? undefined, message: apiResponse.message };\r\n }\r\n\r\n return {\r\n success: false,\r\n message: apiResponse.message || 'Registration failed',\r\n errors: apiResponse.errors,\r\n };\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Registration failed');\r\n onError?.(error);\r\n return { success: false, message: error.message };\r\n }\r\n }, [registerEndpoint, mutate, onLogin, onError, parseResponse, parseAuthResponse]);\r\n\r\n // Logout function\r\n const logout = useCallback(async (): Promise<void> => {\r\n try {\r\n await fetch(logoutEndpoint, { method: 'POST' });\r\n await mutate(null, false);\r\n onLogout?.();\r\n \r\n // Redirect after logout if configured\r\n if (logoutRedirect && typeof window !== 'undefined') {\r\n window.location.href = logoutRedirect;\r\n }\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error('Logout failed');\r\n onError?.(error);\r\n throw error;\r\n }\r\n }, [logoutEndpoint, logoutRedirect, mutate, onLogout, onError]);\r\n\r\n // Refresh user data\r\n const refresh = useCallback(async (): Promise<void> => {\r\n await mutate();\r\n }, [mutate]);\r\n\r\n // Compute derived state using custom isGuestFn\r\n const isGuest = isGuestFn(user ?? null);\r\n const isAuthenticated = !!user && !isGuest;\r\n\r\n // Memoize context value\r\n const contextValue = useMemo<AuthContextValue<TUser>>(() => ({\r\n user: user ?? null,\r\n isLoading,\r\n isAuthenticated,\r\n isGuest,\r\n error: error ?? null,\r\n login,\r\n register,\r\n logout,\r\n refresh,\r\n mutate: refresh,\r\n }), [user, isLoading, isAuthenticated, isGuest, error, login, register, logout, refresh]);\r\n\r\n return (\r\n <AuthContext.Provider value={contextValue}>\r\n {children}\r\n </AuthContext.Provider>\r\n );\r\n}\r\n","'use client';\r\n\r\n/**\r\n * useAuth Hook - Generic for any user type\r\n * \r\n * @example Basic usage\r\n * ```tsx\r\n * const { user, isAuthenticated, logout } = useAuth();\r\n * ```\r\n * \r\n * @example With custom type\r\n * ```tsx\r\n * interface MyUser {\r\n * type: 'guest' | 'superadmin';\r\n * user?: { name: string; };\r\n * }\r\n * \r\n * const { user } = useAuth<MyUser>();\r\n * // user is MyUser | null\r\n * ```\r\n */\r\n\r\nimport { useContext } from 'react';\r\nimport { useRouter } from 'next/navigation';\r\nimport { AuthContext } from './AuthProvider';\r\nimport type { AuthContextValue, UseAuthOptions, DefaultUserData } from './types';\r\n\r\n/**\r\n * Hook to access authentication state and methods\r\n * \r\n * @typeParam TUser - User data type (defaults to DefaultUserData)\r\n */\r\nexport function useAuth<TUser = DefaultUserData>(\r\n options: UseAuthOptions = {}\r\n): AuthContextValue<TUser> {\r\n const context = useContext(AuthContext) as AuthContextValue<TUser> | undefined;\r\n const router = useRouter();\r\n\r\n if (!context) {\r\n throw new Error(\r\n 'useAuth must be used within an AuthProvider. ' +\r\n 'Wrap your app with <AuthProvider> from next-api-layer/client'\r\n );\r\n }\r\n\r\n const { redirectTo, redirectIfFound } = options;\r\n\r\n // Handle redirects based on auth state\r\n if (!context.isLoading) {\r\n if (redirectTo && !context.isAuthenticated && !context.isGuest) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectTo);\r\n }\r\n }\r\n\r\n if (redirectIfFound && context.isAuthenticated) {\r\n if (typeof window !== 'undefined') {\r\n router.replace(redirectIfFound);\r\n }\r\n }\r\n }\r\n\r\n return context;\r\n}\r\n\r\n/**\r\n * Hook to get only the user object\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useUser<TUser = DefaultUserData>() {\r\n const { user, isLoading, isAuthenticated, isGuest } = useAuth<TUser>();\r\n return { user, isLoading, isAuthenticated, isGuest };\r\n}\r\n\r\n/**\r\n * Hook for protected pages - redirects if not authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRequireAuth<TUser = DefaultUserData>(redirectTo = '/login') {\r\n const auth = useAuth<TUser>({ redirectTo });\r\n \r\n if (!auth.isLoading && !auth.isAuthenticated) {\r\n throw new Error('Authentication required');\r\n }\r\n \r\n return auth;\r\n}\r\n\r\n/**\r\n * Hook for auth pages - redirects if already authenticated\r\n * \r\n * @typeParam TUser - User data type\r\n */\r\nexport function useRedirectIfAuth<TUser = DefaultUserData>(redirectTo = '/') {\r\n return useAuth<TUser>({ redirectIfFound: redirectTo });\r\n}\r\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var chunkJEEL6S4O_cjs=require('./chunk-JEEL6S4O.cjs'),chunk6ENVQMWQ_cjs=require('./chunk-6ENVQMWQ.cjs'),server=require('next/server');function ue(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID()+crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2)}`}function le(e){return `rl:${e.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||e.headers.get("x-real-ip")||"unknown"}`}function ee(e){if(!e.apiBaseUrl)throw new Error("next-api-layer: apiBaseUrl is required");if(!e.cookies?.user||!e.cookies?.guest)throw new Error("next-api-layer: cookies.user and cookies.guest are required");let t=e.apiBaseUrl.endsWith("/")?e.apiBaseUrl:`${e.apiBaseUrl}/`,f={...chunk6ENVQMWQ_cjs.a,...e.cookies.options},r={...chunk6ENVQMWQ_cjs.b,...e.endpoints},p={enabled:e.csrf?.enabled??false,strategy:e.csrf?.strategy??chunk6ENVQMWQ_cjs.g.strategy,secret:e.csrf?.secret??ue(),cookieName:e.csrf?.cookieName??chunk6ENVQMWQ_cjs.g.cookieName,headerName:e.csrf?.headerName??chunk6ENVQMWQ_cjs.g.headerName,ignoreMethods:e.csrf?.ignoreMethods??chunk6ENVQMWQ_cjs.g.ignoreMethods,trustSameSite:e.csrf?.trustSameSite??chunk6ENVQMWQ_cjs.g.trustSameSite},R={enabled:e.rateLimit?.enabled??false,windowMs:e.rateLimit?.windowMs??chunk6ENVQMWQ_cjs.h.windowMs,maxRequests:e.rateLimit?.maxRequests??chunk6ENVQMWQ_cjs.h.maxRequests,keyFn:e.rateLimit?.keyFn??le,skipRoutes:e.rateLimit?.skipRoutes??chunk6ENVQMWQ_cjs.h.skipRoutes,onRateLimited:e.rateLimit?.onRateLimited},l={enabled:e.audit?.enabled??false,events:e.audit?.events??[...chunk6ENVQMWQ_cjs.i.events],logger:e.audit?.logger};return {...e,apiBaseUrl:t,_resolved:{cookieOptions:f,endpoints:r,csrf:p,rateLimit:R,audit:l}}}var j={parseAuthMe:e=>{let t=e;return !t?.success||!t?.data?null:{isValid:true,tokenType:t.data.type||"user",exp:t.data.exp||null,userData:t.data}},parseRefreshToken:e=>{let t=e;return t?.success&&t?.data?.accessToken?t.data.accessToken:null},parseGuestToken:e=>e?.data?.accessToken||null};function z(e){let{apiBaseUrl:t,_resolved:f,responseMappers:r}=e,{endpoints:p}=f,R={parseAuthMe:r?.parseAuthMe||j.parseAuthMe,parseRefreshToken:r?.parseRefreshToken||j.parseRefreshToken,parseGuestToken:r?.parseGuestToken||j.parseGuestToken};async function l(i){let u={isValid:false,tokenType:null,exp:null,userData:null};try{let n=await fetch(`${t}${p.validate}`,{headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},cache:"no-store"});if(!n.ok)return u;let s=await n.json().catch(()=>null),d=R.parseAuthMe(s);return !d||!d.isValid?u:d}catch{return u}}async function c(i){return l(i)}async function m(i){try{let u=await fetch(`${t}${p.refresh}`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},cache:"no-store"});if(!u.ok)return {success:!1,newToken:null};let n=await u.json().catch(()=>null),s=R.parseRefreshToken(n);return s?{success:!0,newToken:s}:{success:!1,newToken:null}}catch{return {success:false,newToken:null}}}async function o(){let i=e.guestToken;if(!i?.enabled||!i.credentials)return null;try{let u=await fetch(`${t}${p.guest}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:i.credentials.username,password:i.credentials.password}),cache:"no-store"});if(!u.ok)return null;let n=await u.json().catch(()=>null);return R.parseGuestToken(n)}catch{return null}}return {validateToken:l,getTokenInfo:c,refreshToken:m,createGuestToken:o}}function O(e,t){if(!t?.enabled)return null;let f=t.locales??[],r=t.defaultLocale,R=e.split("/").filter(Boolean)[0];return R&&f.includes(R)?R:r??null}function K(e,t){let{cookies:f,guestToken:r,access:p,i18n:R,_resolved:l}=e,{cookieOptions:c}=l;function m(a,x,h){a.cookies.get(h)?.value&&x.cookies.delete(h);}function o(a,x){return m(a,x,f.guest),m(a,x,f.user),x}function i(a,x=500){return new server.NextResponse(JSON.stringify({success:false,message:a}),{status:x,headers:{"Content-Type":"application/json"}})}function u(a){return (p?.authRoutes??[]).some(h=>a===h||a.startsWith(`${h}/`))}function n(a){return p?.protectedByDefault?!s(a)&&!u(a):(p?.protectedRoutes??[]).some(h=>a===h||a.startsWith(`${h}/`))}function s(a){return (p?.publicRoutes??[]).some(h=>a===h||a.startsWith(`${h}/`))}function d(a){let x=p?.allowedTokenTypes;return !x||x.length===0?true:a?x.includes(a):false}async function N(a,x){let{origin:h}=a.nextUrl;if(r?.enabled){let k=await t.createGuestToken();if(k){let L;return x?L=server.NextResponse.next():n(a.nextUrl.pathname)?L=server.NextResponse.redirect(new URL("/login",h)):L=server.NextResponse.next(),L.cookies.set(f.guest,k,{...c,maxAge:3600}),L}}return x?i("Token bulunamad\u0131",401):n(a.nextUrl.pathname)?server.NextResponse.redirect(new URL("/login",h)):server.NextResponse.next()}async function E(a,x,h,k,L){let{pathname:T,origin:g}=a.nextUrl,{isValid:S,tokenType:A,userData:w}=x,v=A===chunk6ENVQMWQ_cjs.c.GUEST;if(!S){if(h&&k){let H=await t.refreshToken(k);if(H.success&&H.newToken){let F=await t.getTokenInfo(H.newToken);if(F.isValid){let _=new Headers(a.headers);F.userData&&_.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(F.userData)),_.set(chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN,H.newToken);let Q=O(T,R);Q&&_.set(chunk6ENVQMWQ_cjs.e.LOCALE,Q);let D;return u(T)?D=server.NextResponse.redirect(new URL("/",g)):D=server.NextResponse.next({request:{headers:_}}),D.cookies.set(f.user,H.newToken,{...c,maxAge:c.maxAge}),m(a,D,f.guest),D}}}let P=await N(a,L);return P.cookies.get(f.guest)?.value?m(a,P,f.user):o(a,P),P}let U=new Headers(a.headers);w&&U.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(w));let X=O(T,R);if(X&&U.set(chunk6ENVQMWQ_cjs.e.LOCALE,X),!v&&!d(A)){if(L){let Z=i("Bu i\u015Flem i\xE7in yetkiniz yok",403);return o(a,Z)}let P=server.NextResponse.redirect(new URL("/login",g));return o(a,P)}if(v)return L?server.NextResponse.next({request:{headers:U}}):n(T)?server.NextResponse.redirect(new URL("/login",g)):server.NextResponse.next({request:{headers:U}});if(u(T))return server.NextResponse.redirect(new URL("/",g));let Y=server.NextResponse.next({request:{headers:U}});return m(a,Y,f.guest),Y}return {deleteAllAuthCookies:o,jsonError:i,isAuthPage:u,isProtectedRoute:n,isPublicRoute:s,isTokenTypeAllowed:d,handleNoToken:N,handleValidationResult:E}}function W(e){async function t(l){let c=ce();return `${await de(e.secret,l,c)}.${c}`}function f(l){let c=l.method.toUpperCase();if(e.ignoreMethods.includes(c))return {valid:true};let m=e.strategy;if(m==="fetch-metadata"||m==="both"){let o=r(l);if(m==="fetch-metadata"||o.valid||o.reason!=="missing-headers")return o}return m==="double-submit"||m==="both"?p(l):{valid:true}}function r(l){let c=l.headers.get("sec-fetch-site");if(!c)return {valid:false,reason:"missing-headers"};if(c==="same-origin")return {valid:true};if(c==="none"){let m=l.method.toUpperCase();return e.ignoreMethods.includes(m)?{valid:true}:{valid:false,reason:"direct-navigation-unsafe-method"}}return c==="same-site"?e.trustSameSite?{valid:true}:{valid:false,reason:"same-site-not-trusted"}:c==="cross-site"?{valid:false,reason:"cross-site-request"}:{valid:false,reason:"unknown-sec-fetch-site"}}function p(l){let c=l.cookies.get(e.cookieName)?.value;if(!c)return {valid:false,reason:"missing-cookie-token"};let m=l.headers.get(e.headerName);return m?fe(c,m)?c.split(".").length!==2?{valid:false,reason:"invalid-token-format"}:{valid:true}:{valid:false,reason:"token-mismatch"}:{valid:false,reason:"missing-header-token"}}async function R(l,c){let m=await t(c);return l.cookies.set(e.cookieName,m,{httpOnly:false,secure:process.env.NODE_ENV==="production",sameSite:"strict",path:"/"}),l}return {validateRequest:f,generateToken:t,attachCsrfCookie:R}}function ce(){if(typeof crypto<"u"&&crypto.getRandomValues){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}return Math.random().toString(36).substring(2)+Date.now().toString(36)}async function de(e,t,f){let r=`${t.length}!${t}!${f.length}!${f}`;if(typeof crypto<"u"&&crypto.subtle){let l=new TextEncoder,c=l.encode(e),m=l.encode(r),o=await crypto.subtle.importKey("raw",c,{name:"HMAC",hash:"SHA-256"},false,["sign"]),i=await crypto.subtle.sign("HMAC",o,m);return Array.from(new Uint8Array(i),u=>u.toString(16).padStart(2,"0")).join("")}let p=0,R=e+r;for(let l=0;l<R.length;l++){let c=R.charCodeAt(l);p=(p<<5)-p+c,p=p&p;}return Math.abs(p).toString(16)}function fe(e,t){if(e.length!==t.length)return false;let f=0;for(let r=0;r<e.length;r++)f|=e.charCodeAt(r)^t.charCodeAt(r);return f===0}function q(e){let t=new Map,f=setInterval(()=>{let i=Date.now();for(let[u,n]of t)n.resetAt<=i&&t.delete(u);},e.windowMs);typeof process<"u"&&process.on&&process.on("beforeExit",()=>clearInterval(f));function r(i){return e.skipRoutes.some(u=>u.endsWith("*")?i.startsWith(u.slice(0,-1)):u.endsWith("**")?i.startsWith(u.slice(0,-2)):i===u)}function p(i){let u=i.nextUrl.pathname;if(r(u))return {allowed:true,remaining:e.maxRequests,resetAt:0,limit:e.maxRequests};let n=e.keyFn(i),s=Date.now(),d=t.get(n);if(!d||d.resetAt<=s)return d={count:1,resetAt:s+e.windowMs},t.set(n,d),{allowed:true,remaining:e.maxRequests-1,resetAt:d.resetAt,limit:e.maxRequests};d.count++;let N=Math.max(0,e.maxRequests-d.count);return {allowed:d.count<=e.maxRequests,remaining:N,resetAt:d.resetAt,limit:e.maxRequests}}function R(i,u){return i.headers.set("X-RateLimit-Limit",u.limit.toString()),i.headers.set("X-RateLimit-Remaining",u.remaining.toString()),i.headers.set("X-RateLimit-Reset",Math.ceil(u.resetAt/1e3).toString()),i}function l(i,u){if(e.onRateLimited){let s=e.onRateLimited(i);return R(s,u)}let n=server.NextResponse.json({success:false,message:"Too many requests. Please try again later.",retryAfter:Math.ceil((u.resetAt-Date.now())/1e3)},{status:429});return n.headers.set("Retry-After",Math.ceil((u.resetAt-Date.now())/1e3).toString()),R(n,u)}function c(i){t.delete(i);}function m(){t.clear();}function o(){return t.size}return {check:p,applyHeaders:R,createLimitedResponse:l,shouldSkip:r,reset:c,clear:m,size:o}}function J(e){function t(n){return e.enabled&&e.events.includes(n)}function f(n){return n.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||n.headers.get("x-real-ip")||null}async function r(n,s,d){if(!t(n))return;let N={type:n,timestamp:new Date,ip:f(s),userId:d.userId,path:s.nextUrl.pathname,method:s.method,success:d.success,metadata:d.metadata};if(e.logger)try{await e.logger(N);}catch(E){console.error("[next-api-layer] Audit logger error:",E);}}function p(n,s,d){return r("auth:success",n,{success:true,userId:s,metadata:d})}function R(n,s){return r("auth:fail",n,{success:false,metadata:s})}function l(n,s,d){return r("auth:refresh",n,{success:true,userId:s,metadata:d})}function c(n,s){return r("auth:guest",n,{success:true,metadata:s})}function m(n,s,d){return r("access:denied",n,{success:false,userId:s,metadata:d})}function o(n,s){return r("csrf:fail",n,{success:false,metadata:s})}function i(n,s){return r("rateLimit:exceeded",n,{success:false,metadata:s})}function u(n,s,d){return r("error",n,{success:false,metadata:{...d,error:s.message,stack:s.stack}})}return {emit:r,isEnabled:t,authSuccess:p,authFail:R,authRefresh:l,authGuest:c,accessDenied:m,csrfFail:o,rateLimitExceeded:i,error:u}}function te(e,t){let f=[chunk6ENVQMWQ_cjs.e.LOCALE,chunk6ENVQMWQ_cjs.e.AUTH_USER,chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN];for(let r of f){let p=e.headers.get(r);p&&!t.headers.has(r)&&t.headers.set(r,p);}return e.cookies.getAll().forEach(r=>{t.cookies.get(r.name)||t.cookies.set(r.name,r.value);}),t}function se(e){let t=ee(e),f=z(t),r=K(t,f),p=W(t._resolved.csrf),R=q(t._resolved.rateLimit),l=J(t._resolved.audit);async function c(o){let{pathname:i,origin:u}=o.nextUrl,n=i.startsWith("/api");if(t._resolved.rateLimit.enabled){let g=R.check(o);if(!g.allowed)return await l.rateLimitExceeded(o,{limit:g.limit,resetAt:g.resetAt}),R.createLimitedResponse(o,g)}if(t._resolved.csrf.enabled){let g=p.validateRequest(o);if(!g.valid)return await l.csrfFail(o,{reason:g.reason}),server.NextResponse.json({success:false,message:"CSRF validation failed"},{status:403})}if(t.blockBrowserApiAccess&&n&&(o.headers.get("accept")||"").includes("text/html"))return server.NextResponse.redirect(new URL("/",u));if(t.beforeAuth){let g=await t.beforeAuth(o);if(g)return g}if((t.excludedPaths??[]).some(g=>i.startsWith(g)))return m(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});if(["/api/auth/login","/api/auth/logout","/api/auth/me","/api/auth/refresh","/api/auth/register"].includes(i))return m(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});let N=o.cookies?.get(t.cookies.user)?.value,E=o.cookies?.get(t.cookies.guest)?.value,a=N||E,x=!!N;if(!a){await l.authFail(o,{reason:"no-token"});let g=await r.handleNoToken(o,n);return m(o,g,{isAuthenticated:false,isGuest:false,tokenType:null,user:null})}let h=await f.getTokenInfo(a),k={isAuthenticated:h.isValid&&h.tokenType!=="guest",isGuest:h.isValid&&h.tokenType==="guest",tokenType:h.tokenType,user:h.userData};if(h.isValid)if(h.tokenType==="guest")await l.authGuest(o);else {let g=h.userData?.id?.toString();await l.authSuccess(o,g,{tokenType:h.tokenType});}else await l.authFail(o,{reason:"invalid-token"});let L=await r.handleValidationResult(o,h,x,a,n),T=await m(o,L,k);if(t._resolved.csrf.enabled&&k.isAuthenticated){let g=h.userData?.id?.toString()||a.slice(0,32);T=await p.attachCsrfCookie(T,g);}if(t._resolved.rateLimit.enabled){let g=R.check(o);T=R.applyHeaders(T,g);}return T}async function m(o,i,u){let n=i;if(t.i18n?.middleware){let s=await Promise.resolve(t.i18n.middleware(o));n=te(i,s);}if(t.i18n?.enabled){let s=O(o.nextUrl.pathname,t.i18n);s&&n.headers.set(chunk6ENVQMWQ_cjs.e.LOCALE,s);}if(t.afterAuth){let s=await t.afterAuth(o,n,u);n=te(n,s);}return n}return c.config=t,c.csrf=p,c.rateLimiter=R,c.audit=l,c}function me(e,t){if(!t||t.length===0)return false;let f=e.replace(/^\/api\//,"").replace(/^\//,"");return t.some(r=>{if(r===f)return true;if(r.includes("*")){let p=r.replace(/\*\*/g,"<<<DOUBLE>>>").replace(/\*/g,"[^/]+").replace(/<<<DOUBLE>>>/g,".+");return new RegExp(`^${p}$`).test(f)}return false})}function re(e){let{apiBaseUrl:t,userCookieName:f="auth_token",guestCookieName:r="guest_token",skipAuthByDefault:p=false,publicEndpoints:R=[],forwardHeaders:l=["content-type","accept","accept-language","x-requested-with"],excludeHeaders:c=["host","connection","cookie"],transformRequest:m,transformResponse:o}=e,i=t.replace(/\/$/,"");function u(s,d){return s.headers.get(chunk6ENVQMWQ_cjs.e.SKIP_AUTH)==="true"||me(d,R)?true:p}async function n(s){try{let d=new URL(s.url),N=d.pathname.replace(/^\/api\/?/,""),E=new URL(`${i}/${N}`);E.search=d.search;let a=new Headers;if(l.forEach(A=>{let w=s.headers.get(A);w&&a.set(A,w);}),s.headers.forEach((A,w)=>{let v=w.toLowerCase();!c.includes(v)&&!a.has(w)&&a.set(w,A);}),!u(s,N)){let A=s.cookies.get(f)?.value,w=s.cookies.get(r)?.value,v=A||w;v&&a.set(chunk6ENVQMWQ_cjs.e.AUTHORIZATION,`Bearer ${v}`);}a.delete(chunk6ENVQMWQ_cjs.e.SKIP_AUTH);let x=m?await m(s,a):a,h=null;if(s.method!=="GET"&&s.method!=="HEAD"){let A=s.headers.get("content-type")||"";A.includes("application/json")?h=await s.text():A.includes("multipart/form-data")?h=await s.formData():h=await s.text();}let k=await fetch(E.toString(),{method:s.method,headers:x,body:h}),L=k.headers.get("content-type")||"",T;L.includes("application/json")?T=await k.text():T=await k.arrayBuffer();let g=new Headers;k.headers.forEach((A,w)=>{let v=w.toLowerCase();["transfer-encoding","connection","keep-alive"].includes(v)||g.set(w,A);});let S=new server.NextResponse(T,{status:k.status,statusText:k.statusText,headers:g});return o&&(S=await o(S)),S}catch(d){return console.error("[Proxy Error]",d),server.NextResponse.json({success:false,message:"Proxy error: Unable to connect to backend",error:d instanceof Error?d.message:"Unknown error"},{status:502})}}return n.config=e,n}
|
|
2
|
-
Object.defineProperty(exports,"createApiClient",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.d}});Object.defineProperty(exports,"CSRF_SAFE_METHODS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.f}});Object.defineProperty(exports,"DEFAULT_AUDIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.i}});Object.defineProperty(exports,"DEFAULT_COOKIE_OPTIONS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.a}});Object.defineProperty(exports,"DEFAULT_CSRF_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.g}});Object.defineProperty(exports,"DEFAULT_ENDPOINTS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.b}});Object.defineProperty(exports,"DEFAULT_RATE_LIMIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.h}});Object.defineProperty(exports,"ERROR_MESSAGES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.d}});Object.defineProperty(exports,"HEADERS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.e}});Object.defineProperty(exports,"TOKEN_TYPES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.c}});exports.createAuditLogger=
|
|
1
|
+
'use strict';var chunkJEEL6S4O_cjs=require('./chunk-JEEL6S4O.cjs'),chunk6ENVQMWQ_cjs=require('./chunk-6ENVQMWQ.cjs'),server=require('next/server');function le(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID()+crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2)}`}function ce(e){return `rl:${e.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||e.headers.get("x-real-ip")||"unknown"}`}function te(e){if(!e.apiBaseUrl)throw new Error("next-api-layer: apiBaseUrl is required");if(!e.cookies?.user||!e.cookies?.guest)throw new Error("next-api-layer: cookies.user and cookies.guest are required");let t=e.apiBaseUrl.endsWith("/")?e.apiBaseUrl:`${e.apiBaseUrl}/`,d={...chunk6ENVQMWQ_cjs.a,...e.cookies.options},r={...chunk6ENVQMWQ_cjs.b,...e.endpoints},c={enabled:e.csrf?.enabled??false,strategy:e.csrf?.strategy??chunk6ENVQMWQ_cjs.g.strategy,secret:e.csrf?.secret??le(),cookieName:e.csrf?.cookieName??chunk6ENVQMWQ_cjs.g.cookieName,headerName:e.csrf?.headerName??chunk6ENVQMWQ_cjs.g.headerName,ignoreMethods:e.csrf?.ignoreMethods??chunk6ENVQMWQ_cjs.g.ignoreMethods,trustSameSite:e.csrf?.trustSameSite??chunk6ENVQMWQ_cjs.g.trustSameSite},m={enabled:e.rateLimit?.enabled??false,windowMs:e.rateLimit?.windowMs??chunk6ENVQMWQ_cjs.h.windowMs,maxRequests:e.rateLimit?.maxRequests??chunk6ENVQMWQ_cjs.h.maxRequests,keyFn:e.rateLimit?.keyFn??ce,skipRoutes:e.rateLimit?.skipRoutes??chunk6ENVQMWQ_cjs.h.skipRoutes,onRateLimited:e.rateLimit?.onRateLimited},l={enabled:e.audit?.enabled??false,events:e.audit?.events??[...chunk6ENVQMWQ_cjs.i.events],logger:e.audit?.logger};return {...e,apiBaseUrl:t,_resolved:{cookieOptions:d,endpoints:r,csrf:c,rateLimit:m,audit:l}}}var j={parseAuthMe:e=>{let t=e;return !t?.success||!t?.data?null:{isValid:true,tokenType:t.data.type||"user",exp:t.data.exp||null,userData:t.data}},parseRefreshToken:e=>{let t=e;return t?.success&&t?.data?.accessToken?t.data.accessToken:null},parseGuestToken:e=>e?.data?.accessToken||null};function z(e){let{apiBaseUrl:t,_resolved:d,responseMappers:r}=e,{endpoints:c}=d,m={parseAuthMe:r?.parseAuthMe||j.parseAuthMe,parseRefreshToken:r?.parseRefreshToken||j.parseRefreshToken,parseGuestToken:r?.parseGuestToken||j.parseGuestToken};async function l(a){let u={isValid:false,tokenType:null,exp:null,userData:null};try{let n=await fetch(`${t}${c.validate}`,{headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},cache:"no-store"});if(!n.ok)return u;let s=await n.json().catch(()=>null),p=m.parseAuthMe(s);return !p||!p.isValid?u:p}catch{return u}}async function f(a){return l(a)}async function h(a){try{let u=await fetch(`${t}${c.refresh}`,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},cache:"no-store"});if(!u.ok)return {success:!1,newToken:null};let n=await u.json().catch(()=>null),s=m.parseRefreshToken(n);return s?{success:!0,newToken:s}:{success:!1,newToken:null}}catch{return {success:false,newToken:null}}}async function o(){let a=e.guestToken;if(!a?.enabled||!a.credentials)return null;try{let u=await fetch(`${t}${c.guest}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({username:a.credentials.username,password:a.credentials.password}),cache:"no-store"});if(!u.ok)return null;let n=await u.json().catch(()=>null);return m.parseGuestToken(n)}catch{return null}}return {validateToken:l,getTokenInfo:f,refreshToken:h,createGuestToken:o}}function O(e,t){if(!t?.enabled)return null;let d=t.locales??[],r=t.defaultLocale,m=e.split("/").filter(Boolean)[0];return m&&d.includes(m)?m:r??null}function K(e,t){if(!t?.enabled)return e;let d=t.locales??[],r=e.split("/").filter(Boolean),c=r[0];return c&&d.includes(c)?"/"+r.slice(1).join("/")||"/":e}function W(e,t){let{cookies:d,guestToken:r,access:c,i18n:m,_resolved:l}=e,{cookieOptions:f}=l;function h(i,R,x){i.cookies.get(x)?.value&&R.cookies.delete(x);}function o(i,R){return h(i,R,d.guest),h(i,R,d.user),R}function a(i,R=500){return new server.NextResponse(JSON.stringify({success:false,message:i}),{status:R,headers:{"Content-Type":"application/json"}})}function u(i){let R=K(i,m);return (c?.authRoutes??[]).some(y=>R===y||R.startsWith(`${y}/`))}function n(i){let R=K(i,m);return c?.protectedByDefault?!s(i)&&!u(i):(c?.protectedRoutes??[]).some(y=>R===y||R.startsWith(`${y}/`))}function s(i){let R=K(i,m);return (c?.publicRoutes??[]).some(y=>R===y||R.startsWith(`${y}/`))}function p(i){let R=c?.allowedTokenTypes;return !R||R.length===0?true:i?R.includes(i):false}async function N(i,R){let{origin:x}=i.nextUrl;if(r?.enabled){let y=await t.createGuestToken();if(y){let L;return R?L=server.NextResponse.next():n(i.nextUrl.pathname)?L=server.NextResponse.redirect(new URL("/login",x)):L=server.NextResponse.next(),L.cookies.set(d.guest,y,{...f,maxAge:3600}),L}}return R?a("Token bulunamad\u0131",401):n(i.nextUrl.pathname)?server.NextResponse.redirect(new URL("/login",x)):server.NextResponse.next()}async function E(i,R,x,y,L){let{pathname:T,origin:g}=i.nextUrl,{isValid:S,tokenType:A,userData:w}=R,v=A===chunk6ENVQMWQ_cjs.c.GUEST;if(!S){if(x&&y){let H=await t.refreshToken(y);if(H.success&&H.newToken){let F=await t.getTokenInfo(H.newToken);if(F.isValid){let _=new Headers(i.headers);F.userData&&_.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(F.userData)),_.set(chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN,H.newToken);let ee=O(T,m);ee&&_.set(chunk6ENVQMWQ_cjs.e.LOCALE,ee);let D;return u(T)?D=server.NextResponse.redirect(new URL("/",g)):D=server.NextResponse.next({request:{headers:_}}),D.cookies.set(d.user,H.newToken,{...f,maxAge:f.maxAge}),h(i,D,d.guest),D}}}let b=await N(i,L);return b.cookies.get(d.guest)?.value?h(i,b,d.user):o(i,b),b}let U=new Headers(i.headers);w&&U.set(chunk6ENVQMWQ_cjs.e.AUTH_USER,JSON.stringify(w));let Y=O(T,m);if(Y&&U.set(chunk6ENVQMWQ_cjs.e.LOCALE,Y),!v&&!p(A)){if(L){let Q=a("Bu i\u015Flem i\xE7in yetkiniz yok",403);return o(i,Q)}let b=server.NextResponse.redirect(new URL("/login",g));return o(i,b)}if(v)return L?server.NextResponse.next({request:{headers:U}}):n(T)?server.NextResponse.redirect(new URL("/login",g)):server.NextResponse.next({request:{headers:U}});if(u(T))return server.NextResponse.redirect(new URL("/",g));let Z=server.NextResponse.next({request:{headers:U}});return h(i,Z,d.guest),Z}return {deleteAllAuthCookies:o,jsonError:a,isAuthPage:u,isProtectedRoute:n,isPublicRoute:s,isTokenTypeAllowed:p,handleNoToken:N,handleValidationResult:E}}function q(e){async function t(l){let f=de();return `${await fe(e.secret,l,f)}.${f}`}function d(l){let f=l.method.toUpperCase();if(e.ignoreMethods.includes(f))return {valid:true};let h=e.strategy;if(h==="fetch-metadata"||h==="both"){let o=r(l);if(h==="fetch-metadata"||o.valid||o.reason!=="missing-headers")return o}return h==="double-submit"||h==="both"?c(l):{valid:true}}function r(l){let f=l.headers.get("sec-fetch-site");if(!f)return {valid:false,reason:"missing-headers"};if(f==="same-origin")return {valid:true};if(f==="none"){let h=l.method.toUpperCase();return e.ignoreMethods.includes(h)?{valid:true}:{valid:false,reason:"direct-navigation-unsafe-method"}}return f==="same-site"?e.trustSameSite?{valid:true}:{valid:false,reason:"same-site-not-trusted"}:f==="cross-site"?{valid:false,reason:"cross-site-request"}:{valid:false,reason:"unknown-sec-fetch-site"}}function c(l){let f=l.cookies.get(e.cookieName)?.value;if(!f)return {valid:false,reason:"missing-cookie-token"};let h=l.headers.get(e.headerName);return h?pe(f,h)?f.split(".").length!==2?{valid:false,reason:"invalid-token-format"}:{valid:true}:{valid:false,reason:"token-mismatch"}:{valid:false,reason:"missing-header-token"}}async function m(l,f){let h=await t(f);return l.cookies.set(e.cookieName,h,{httpOnly:false,secure:process.env.NODE_ENV==="production",sameSite:"strict",path:"/"}),l}return {validateRequest:d,generateToken:t,attachCsrfCookie:m}}function de(){if(typeof crypto<"u"&&crypto.getRandomValues){let e=new Uint8Array(32);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}return Math.random().toString(36).substring(2)+Date.now().toString(36)}async function fe(e,t,d){let r=`${t.length}!${t}!${d.length}!${d}`;if(typeof crypto<"u"&&crypto.subtle){let l=new TextEncoder,f=l.encode(e),h=l.encode(r),o=await crypto.subtle.importKey("raw",f,{name:"HMAC",hash:"SHA-256"},false,["sign"]),a=await crypto.subtle.sign("HMAC",o,h);return Array.from(new Uint8Array(a),u=>u.toString(16).padStart(2,"0")).join("")}let c=0,m=e+r;for(let l=0;l<m.length;l++){let f=m.charCodeAt(l);c=(c<<5)-c+f,c=c&c;}return Math.abs(c).toString(16)}function pe(e,t){if(e.length!==t.length)return false;let d=0;for(let r=0;r<e.length;r++)d|=e.charCodeAt(r)^t.charCodeAt(r);return d===0}function J(e){let t=new Map,d=setInterval(()=>{let a=Date.now();for(let[u,n]of t)n.resetAt<=a&&t.delete(u);},e.windowMs);typeof process<"u"&&process.on&&process.on("beforeExit",()=>clearInterval(d));function r(a){return e.skipRoutes.some(u=>u.endsWith("*")?a.startsWith(u.slice(0,-1)):u.endsWith("**")?a.startsWith(u.slice(0,-2)):a===u)}function c(a){let u=a.nextUrl.pathname;if(r(u))return {allowed:true,remaining:e.maxRequests,resetAt:0,limit:e.maxRequests};let n=e.keyFn(a),s=Date.now(),p=t.get(n);if(!p||p.resetAt<=s)return p={count:1,resetAt:s+e.windowMs},t.set(n,p),{allowed:true,remaining:e.maxRequests-1,resetAt:p.resetAt,limit:e.maxRequests};p.count++;let N=Math.max(0,e.maxRequests-p.count);return {allowed:p.count<=e.maxRequests,remaining:N,resetAt:p.resetAt,limit:e.maxRequests}}function m(a,u){return a.headers.set("X-RateLimit-Limit",u.limit.toString()),a.headers.set("X-RateLimit-Remaining",u.remaining.toString()),a.headers.set("X-RateLimit-Reset",Math.ceil(u.resetAt/1e3).toString()),a}function l(a,u){if(e.onRateLimited){let s=e.onRateLimited(a);return m(s,u)}let n=server.NextResponse.json({success:false,message:"Too many requests. Please try again later.",retryAfter:Math.ceil((u.resetAt-Date.now())/1e3)},{status:429});return n.headers.set("Retry-After",Math.ceil((u.resetAt-Date.now())/1e3).toString()),m(n,u)}function f(a){t.delete(a);}function h(){t.clear();}function o(){return t.size}return {check:c,applyHeaders:m,createLimitedResponse:l,shouldSkip:r,reset:f,clear:h,size:o}}function X(e){function t(n){return e.enabled&&e.events.includes(n)}function d(n){return n.headers.get("x-forwarded-for")?.split(",")[0]?.trim()||n.headers.get("x-real-ip")||null}async function r(n,s,p){if(!t(n))return;let N={type:n,timestamp:new Date,ip:d(s),userId:p.userId,path:s.nextUrl.pathname,method:s.method,success:p.success,metadata:p.metadata};if(e.logger)try{await e.logger(N);}catch(E){console.error("[next-api-layer] Audit logger error:",E);}}function c(n,s,p){return r("auth:success",n,{success:true,userId:s,metadata:p})}function m(n,s){return r("auth:fail",n,{success:false,metadata:s})}function l(n,s,p){return r("auth:refresh",n,{success:true,userId:s,metadata:p})}function f(n,s){return r("auth:guest",n,{success:true,metadata:s})}function h(n,s,p){return r("access:denied",n,{success:false,userId:s,metadata:p})}function o(n,s){return r("csrf:fail",n,{success:false,metadata:s})}function a(n,s){return r("rateLimit:exceeded",n,{success:false,metadata:s})}function u(n,s,p){return r("error",n,{success:false,metadata:{...p,error:s.message,stack:s.stack}})}return {emit:r,isEnabled:t,authSuccess:c,authFail:m,authRefresh:l,authGuest:f,accessDenied:h,csrfFail:o,rateLimitExceeded:a,error:u}}function se(e,t){let d=[chunk6ENVQMWQ_cjs.e.LOCALE,chunk6ENVQMWQ_cjs.e.AUTH_USER,chunk6ENVQMWQ_cjs.e.REFRESHED_TOKEN];for(let r of d){let c=e.headers.get(r);c&&!t.headers.has(r)&&t.headers.set(r,c);}return e.cookies.getAll().forEach(r=>{t.cookies.get(r.name)||t.cookies.set(r.name,r.value);}),t}function ne(e){let t=te(e),d=z(t),r=W(t,d),c=q(t._resolved.csrf),m=J(t._resolved.rateLimit),l=X(t._resolved.audit);async function f(o){let{pathname:a,origin:u}=o.nextUrl,n=a.startsWith("/api");if(t._resolved.rateLimit.enabled){let g=m.check(o);if(!g.allowed)return await l.rateLimitExceeded(o,{limit:g.limit,resetAt:g.resetAt}),m.createLimitedResponse(o,g)}if(t._resolved.csrf.enabled){let g=c.validateRequest(o);if(!g.valid)return await l.csrfFail(o,{reason:g.reason}),server.NextResponse.json({success:false,message:"CSRF validation failed"},{status:403})}if(t.blockBrowserApiAccess&&n&&(o.headers.get("accept")||"").includes("text/html"))return server.NextResponse.redirect(new URL("/",u));if(t.beforeAuth){let g=await t.beforeAuth(o);if(g)return g}if((t.excludedPaths??[]).some(g=>a.startsWith(g)))return h(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});if(["/api/auth/login","/api/auth/logout","/api/auth/me","/api/auth/refresh","/api/auth/register"].includes(a))return h(o,server.NextResponse.next(),{isAuthenticated:false,isGuest:false,tokenType:null,user:null});let N=o.cookies?.get(t.cookies.user)?.value,E=o.cookies?.get(t.cookies.guest)?.value,i=N||E,R=!!N;if(!i){await l.authFail(o,{reason:"no-token"});let g=await r.handleNoToken(o,n);return h(o,g,{isAuthenticated:false,isGuest:false,tokenType:null,user:null})}let x=await d.getTokenInfo(i),y={isAuthenticated:x.isValid&&x.tokenType!=="guest",isGuest:x.isValid&&x.tokenType==="guest",tokenType:x.tokenType,user:x.userData};if(x.isValid)if(x.tokenType==="guest")await l.authGuest(o);else {let g=x.userData?.id?.toString();await l.authSuccess(o,g,{tokenType:x.tokenType});}else await l.authFail(o,{reason:"invalid-token"});let L=await r.handleValidationResult(o,x,R,i,n),T=await h(o,L,y);if(t._resolved.csrf.enabled&&y.isAuthenticated){let g=x.userData?.id?.toString()||i.slice(0,32);T=await c.attachCsrfCookie(T,g);}if(t._resolved.rateLimit.enabled){let g=m.check(o);T=m.applyHeaders(T,g);}return T}async function h(o,a,u){let n=a;if(t.i18n?.middleware){let s=await Promise.resolve(t.i18n.middleware(o));n=se(a,s);}if(t.i18n?.enabled){let s=O(o.nextUrl.pathname,t.i18n);s&&n.headers.set(chunk6ENVQMWQ_cjs.e.LOCALE,s);}if(t.afterAuth){let s=await t.afterAuth(o,n,u);n=se(n,s);}return n}return f.config=t,f.csrf=c,f.rateLimiter=m,f.audit=l,f}function he(e,t){if(!t||t.length===0)return false;let d=e.replace(/^\/api\//,"").replace(/^\//,"");return t.some(r=>{if(r===d)return true;if(r.includes("*")){let c=r.replace(/\*\*/g,"<<<DOUBLE>>>").replace(/\*/g,"[^/]+").replace(/<<<DOUBLE>>>/g,".+");return new RegExp(`^${c}$`).test(d)}return false})}function oe(e){let{apiBaseUrl:t,userCookieName:d="auth_token",guestCookieName:r="guest_token",skipAuthByDefault:c=false,publicEndpoints:m=[],forwardHeaders:l=["content-type","accept","accept-language","x-requested-with"],excludeHeaders:f=["host","connection","cookie"],transformRequest:h,transformResponse:o}=e,a=t.replace(/\/$/,"");function u(s,p){return s.headers.get(chunk6ENVQMWQ_cjs.e.SKIP_AUTH)==="true"||he(p,m)?true:c}async function n(s){try{let p=new URL(s.url),N=p.pathname.replace(/^\/api\/?/,""),E=new URL(`${a}/${N}`);E.search=p.search;let i=new Headers;if(l.forEach(A=>{let w=s.headers.get(A);w&&i.set(A,w);}),s.headers.forEach((A,w)=>{let v=w.toLowerCase();!f.includes(v)&&!i.has(w)&&i.set(w,A);}),!u(s,N)){let A=s.cookies.get(d)?.value,w=s.cookies.get(r)?.value,v=A||w;v&&i.set(chunk6ENVQMWQ_cjs.e.AUTHORIZATION,`Bearer ${v}`);}i.delete(chunk6ENVQMWQ_cjs.e.SKIP_AUTH);let R=h?await h(s,i):i,x=null;if(s.method!=="GET"&&s.method!=="HEAD"){let A=s.headers.get("content-type")||"";A.includes("application/json")?x=await s.text():A.includes("multipart/form-data")?x=await s.formData():x=await s.text();}let y=await fetch(E.toString(),{method:s.method,headers:R,body:x}),L=y.headers.get("content-type")||"",T;L.includes("application/json")?T=await y.text():T=await y.arrayBuffer();let g=new Headers;y.headers.forEach((A,w)=>{let v=w.toLowerCase();["transfer-encoding","connection","keep-alive"].includes(v)||g.set(w,A);});let S=new server.NextResponse(T,{status:y.status,statusText:y.statusText,headers:g});return o&&(S=await o(S)),S}catch(p){return console.error("[Proxy Error]",p),server.NextResponse.json({success:false,message:"Proxy error: Unable to connect to backend",error:p instanceof Error?p.message:"Unknown error"},{status:502})}}return n.config=e,n}
|
|
2
|
+
Object.defineProperty(exports,"createApiClient",{enumerable:true,get:function(){return chunkJEEL6S4O_cjs.d}});Object.defineProperty(exports,"CSRF_SAFE_METHODS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.f}});Object.defineProperty(exports,"DEFAULT_AUDIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.i}});Object.defineProperty(exports,"DEFAULT_COOKIE_OPTIONS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.a}});Object.defineProperty(exports,"DEFAULT_CSRF_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.g}});Object.defineProperty(exports,"DEFAULT_ENDPOINTS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.b}});Object.defineProperty(exports,"DEFAULT_RATE_LIMIT_CONFIG",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.h}});Object.defineProperty(exports,"ERROR_MESSAGES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.d}});Object.defineProperty(exports,"HEADERS",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.e}});Object.defineProperty(exports,"TOKEN_TYPES",{enumerable:true,get:function(){return chunk6ENVQMWQ_cjs.c}});exports.createAuditLogger=X;exports.createAuthProxy=ne;exports.createCsrfValidator=q;exports.createHandlers=W;exports.createProxyHandler=oe;exports.createRateLimiter=J;exports.createTokenValidation=z;//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|