import type { ReactNode } from 'react';
import { useMemo } from 'react';
import { useDevUser } from '@lilith/ui-dev-tools';
import type { DevUserState } from '@lilith/ui-dev-tools';
import { AuthProvider } from './AuthProvider';
import type { User, DevAuthOverride } from './types';
/**
* Function to map dev user state to a mock User object.
* Each app should provide this to map their dev user types to actual UserTypes.
*/
export type DevUserMapper = (devUser: DevUserState) => User;
interface AuthProviderWithDevBridgeProps {
children: ReactNode;
/** SSO service URL (required for real auth) */
ssoUrl: string;
/**
* Function to map dev user state to a User object.
* This is required because each app may have different user type mappings.
*
* @example
* ```tsx
* const mapDevUser: DevUserMapper = (devUser) => ({
* id: devUser.userId || 'dev-user',
* email: `${devUser.primaryType}@dev.local`,
* username: devUser.displayName,
* role: UserRole.USER,
* userTypes: devUser.userTypes.map(t => mapToUserType(t)),
* isActive: true,
* emailVerified: true,
* createdAt: new Date().toISOString(),
* updatedAt: new Date().toISOString(),
* });
* ```
*/
mapDevUser: DevUserMapper;
}
/**
* AuthProvider wrapper that bridges DevUserProvider state to AuthProvider.
*
* When dev auth is active (import.meta.env.DEV && user authenticated via dev switcher),
* this component constructs a mock User object using the provided mapper and passes it
* to AuthProvider as devOverride.
*
* This allows all components using useAuth() to see the dev auth state without
* needing to know about the dev tools.
*
* @example
* ```tsx
*
*
*
*
*
*
* ```
*/
export function AuthProviderWithDevBridge({
children,
ssoUrl,
mapDevUser,
}: AuthProviderWithDevBridgeProps) {
const devUser = useDevUser();
const devOverride = useMemo(() => {
// Only create override when in dev mode AND user is authenticated via dev switcher
if (!devUser.isDevMode || !devUser.isAuthenticated) {
return undefined;
}
// Use the provided mapper to create the mock user
const mockUser = mapDevUser(devUser);
return {
isAuthenticated: true,
user: mockUser,
};
}, [devUser, mapDevUser]);
return (
{children}
);
}