npm package: @pixygon/auth
Description: Shared authentication package for all Pixygon applications
Author: Pixygon
Latest version: 1.1.0

# @pixygon/auth

Shared authentication package for all Pixygon applications (Pixygon.ai, BimboChat, MonsterTask, etc.)

## Features

- Unified authentication across all Pixygon apps
- Automatic token refresh
- Secure token storage with app-specific prefixes
- TypeScript support
- Pre-built branded components
- React hooks for easy integration

## Installation

```bash
# In monorepo, add as local dependency
npm install @pixygon/auth

# Or link locally
npm link ../pixygon-packages/@pixygon/auth
```

## Quick Start

### 1. Wrap your app with AuthProvider

```tsx
import { AuthProvider } from '@pixygon/auth';

function App() {
  return (
    <AuthProvider
      config={{
        baseUrl: 'https://api.pixygon.com/v1',
        appId: 'pixygon-ai', // Unique ID for token storage
        appName: 'Pixygon AI',
        debug: process.env.NODE_ENV === 'development',
        onLogin: (user) => console.log('Logged in:', user.userName),
        onLogout: () => console.log('Logged out'),
      }}
    >
      <YourApp />
    </AuthProvider>
  );
}
```

### 2. Use the auth hooks

```tsx
import { useAuth, useUser } from '@pixygon/auth';

function MyComponent() {
  const { login, logout, isAuthenticated, isLoading } = useAuth();
  const { userName, email, totalTokens } = useUser();

  const handleLogin = async () => {
    try {
      await login({ userName: 'user', password: 'pass' });
    } catch (error) {
      console.error('Login failed:', error.message);
    }
  };

  if (isLoading) return <div>Loading...</div>;

  return isAuthenticated ? (
    <div>
      <p>Welcome, {userName}!</p>
      <p>Tokens: {totalTokens}</p>
      <button onClick={logout}>Logout</button>
    </div>
  ) : (
    <button onClick={handleLogin}>Login</button>
  );
}
```

### 3. Or use the pre-built components

```tsx
import { PixygonAuth } from '@pixygon/auth/components';

function LoginPage() {
  return (
    <PixygonAuth
      mode="login"
      onSuccess={(user) => navigate('/dashboard')}
      onModeChange={(mode) => navigate(`/auth/${mode}`)}
      theme="dark"
    />
  );
}
```

## Available Hooks

### `useAuth()`
Main hook with all auth state and actions.
```tsx
const {
  user,
  status, // 'idle' | 'loading' | 'authenticated' | 'unauthenticated' | 'verifying'
  isAuthenticated,
  isLoading,
  error,
  login,
  register,
  logout,
  verify,
  forgotPassword,
  recoverPassword,
  hasRole,
} = useAuth();
```

### `useUser()`
User data with convenient shortcuts.
```tsx
const {
  user,
  userName,
  email,
  role,
  totalTokens,
  subscriptionTier,
  hasRole,
} = useUser();
```

### `useToken()`
Token management.
```tsx
const {
  accessToken,
  refreshToken,
  getAccessToken,
  refreshTokens,
} = useToken();
```

### `useAuthStatus()`
Status checks.
```tsx
const {
  isIdle,
  isLoading,
  isAuthenticated,
  isUnauthenticated,
  isVerifying,
} = useAuthStatus();
```

### `useRequireAuth()`
Protected routes.
```tsx
const { isAuthorized, isLoading } = useRequireAuth({
  roles: ['admin', 'superadmin'],
  onUnauthorized: () => navigate('/login'),
});
```

## Integration with Redux

If your app uses Redux, you can sync the auth state:

```tsx
import { AuthProvider, useAuth } from '@pixygon/auth';
import { useDispatch } from 'react-redux';
import { setLogin, setLogout } from './state';

// Create a sync component
function AuthReduxSync({ children }) {
  const { user, accessToken, isAuthenticated } = useAuth();
  const dispatch = useDispatch();

  useEffect(() => {
    if (isAuthenticated && user && accessToken) {
      dispatch(setLogin({ user, token: accessToken }));
    } else if (!isAuthenticated) {
      dispatch(setLogout());
    }
  }, [isAuthenticated, user, accessToken, dispatch]);

  return children;
}

// Use it inside AuthProvider
function App() {
  return (
    <AuthProvider config={authConfig}>
      <ReduxProvider store={store}>
        <AuthReduxSync>
          <YourApp />
        </AuthReduxSync>
      </ReduxProvider>
    </AuthProvider>
  );
}
```

## Components

### Individual Forms
```tsx
import { LoginForm, RegisterForm, VerifyForm, ForgotPasswordForm } from '@pixygon/auth/components';
```

### All-in-one Component
```tsx
import { PixygonAuth } from '@pixygon/auth/components';

<PixygonAuth
  mode="login" // 'login' | 'register' | 'verify' | 'forgot-password'
  onSuccess={(user) => {}}
  onError={(error) => {}}
  onModeChange={(mode) => {}}
  userName="user" // For verify mode
  showBranding={true}
  theme="dark" // 'dark' | 'light'
/>
```

## Configuration Options

```tsx
interface AuthConfig {
  // Required
  baseUrl: string;      // API base URL
  appId: string;        // Unique app identifier

  // Optional
  appName?: string;     // Display name
  autoRefresh?: boolean; // Auto-refresh tokens (default: true)
  refreshThreshold?: number; // Seconds before expiry to refresh (default: 300)
  debug?: boolean;      // Enable debug logging

  // Callbacks
  onLogin?: (user: User) => void;
  onLogout?: () => void;
  onTokenRefresh?: (tokens: TokenPair) => void;
  onError?: (error: AuthError) => void;

  // Custom storage (default: localStorage)
  storage?: AuthStorage;
}
```

## API Client (Advanced)

For making authenticated API calls outside of React:

```tsx
import { createAuthApiClient, createTokenStorage } from '@pixygon/auth';

const storage = createTokenStorage('my-app');
const client = createAuthApiClient(config, storage);

// Make authenticated requests
const user = await client.getMe();
const profile = await client.updateProfile({ displayName: 'New Name' });
```

## License

MIT - Pixygon