feat(auth-provider): ✨ Implement dev bridge logic for local auth scenarios with mock token support
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
021cb809f5
commit
c92ba57852
1 changed files with 25 additions and 50 deletions
|
|
@ -1,8 +1,9 @@
|
|||
import type { ReactNode } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useDevUser } from '@lilith/ui-dev-tools';
|
||||
import { AuthProvider } from './AuthProvider';
|
||||
import type { User, DevAuthOverride } from './types';
|
||||
import type { DevUserState, DevUserContextValue } from '@lilith/ui-dev-tools';
|
||||
import type { DevUserState } from '@lilith/ui-dev-tools';
|
||||
|
||||
/**
|
||||
* Function to map dev user state to a mock User object.
|
||||
|
|
@ -36,50 +37,6 @@ interface AuthProviderWithDevBridgeProps {
|
|||
mapDevUser: DevUserMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner component that tries to use DevUser context.
|
||||
* If context is unavailable, falls back to just AuthProvider.
|
||||
*/
|
||||
function AuthProviderWithDevBridgeInner({
|
||||
children,
|
||||
ssoUrl,
|
||||
mapDevUser,
|
||||
}: AuthProviderWithDevBridgeProps) {
|
||||
// Try to get dev user context - this may throw if DevUserProvider is from a different module instance
|
||||
let devUser: DevUserContextValue | null = null;
|
||||
let contextError = false;
|
||||
|
||||
try {
|
||||
// Dynamic require to avoid static analysis issues
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const devTools = require('@lilith/ui-dev-tools');
|
||||
devUser = devTools.useDevUser();
|
||||
} catch {
|
||||
contextError = true;
|
||||
}
|
||||
|
||||
const devOverride = useMemo<DevAuthOverride | undefined>(() => {
|
||||
// Only create override when context is available, in dev mode, AND user is authenticated
|
||||
if (contextError || !devUser || !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, contextError]);
|
||||
|
||||
return (
|
||||
<AuthProvider ssoUrl={ssoUrl} devOverride={devOverride}>
|
||||
{children}
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AuthProvider wrapper that bridges DevUserProvider state to AuthProvider.
|
||||
*
|
||||
|
|
@ -90,9 +47,7 @@ function AuthProviderWithDevBridgeInner({
|
|||
* This allows all components using useAuth() to see the dev auth state without
|
||||
* needing to know about the dev tools.
|
||||
*
|
||||
* NOTE: This component is resilient to module instance duplication issues that
|
||||
* can occur with Vite and other bundlers. If DevUserProvider is not found,
|
||||
* it will fall back to standard AuthProvider behavior.
|
||||
* Must be rendered inside a <DevUserProvider> for the bridge to work.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
|
|
@ -104,6 +59,26 @@ function AuthProviderWithDevBridgeInner({
|
|||
* </DevUserProvider>
|
||||
* ```
|
||||
*/
|
||||
export function AuthProviderWithDevBridge(props: AuthProviderWithDevBridgeProps) {
|
||||
return <AuthProviderWithDevBridgeInner {...props} />;
|
||||
export function AuthProviderWithDevBridge({
|
||||
children,
|
||||
ssoUrl,
|
||||
mapDevUser,
|
||||
}: AuthProviderWithDevBridgeProps) {
|
||||
const devUser = useDevUser();
|
||||
|
||||
const devOverride = useMemo<DevAuthOverride | undefined>(() => {
|
||||
if (!devUser.isDevMode || !devUser.isAuthenticated) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
isAuthenticated: true,
|
||||
user: mapDevUser(devUser),
|
||||
};
|
||||
}, [devUser, mapDevUser]);
|
||||
|
||||
return (
|
||||
<AuthProvider ssoUrl={ssoUrl} devOverride={devOverride}>
|
||||
{children}
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue