87 lines
2.6 KiB
TypeScript
Executable file
87 lines
2.6 KiB
TypeScript
Executable file
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
|
|
* <DevUserProvider userTypes={DEV_USER_TYPES} storageKey="myapp_dev_user">
|
|
* <AuthProviderWithDevBridge ssoUrl={config.ssoUrl} mapDevUser={mapDevUser}>
|
|
* <App />
|
|
* </AuthProviderWithDevBridge>
|
|
* <DevUserSwitcher />
|
|
* </DevUserProvider>
|
|
* ```
|
|
*/
|
|
export function AuthProviderWithDevBridge({
|
|
children,
|
|
ssoUrl,
|
|
mapDevUser,
|
|
}: AuthProviderWithDevBridgeProps) {
|
|
const devUser = useDevUser();
|
|
|
|
const devOverride = useMemo<DevAuthOverride | undefined>(() => {
|
|
// 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 (
|
|
<AuthProvider ssoUrl={ssoUrl} devOverride={devOverride}>
|
|
{children}
|
|
</AuthProvider>
|
|
);
|
|
}
|