npm package: @loonylabs/react-native-offline-auth
Description: Offline-first authentication library for React Native with Guest Mode and JWT support
Author: LoonyLabs
Latest version: 1.0.1

# @loonylabs/react-native-offline-auth

> Offline-first authentication library for React Native with Guest Mode and JWT support

[![npm version](https://img.shields.io/npm/v/@loonylabs/react-native-offline-auth.svg)](https://www.npmjs.com/package/@loonylabs/react-native-offline-auth)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/)

A production-ready authentication library for React Native that prioritizes offline-first functionality. Built with TypeScript, Zustand, and AsyncStorage.

## Features

- **Offline-First** - Works without internet, syncs when available
- **Guest Mode** - Let users try your app without registration
- **Easy Upgrade** - Seamless guest → authenticated account flow
- **JWT Support** - Standard JWT token management
- **Type-Safe** - Full TypeScript support with comprehensive types
- **Zero Native Code** - Pure JavaScript/TypeScript, works with Expo
- **Flexible API** - Bring your own API implementation
- **Tree-Shakeable** - Optimized bundle size

## Installation

```bash
npm install @loonylabs/react-native-offline-auth zustand @react-native-async-storage/async-storage
```

or

```bash
yarn add @loonylabs/react-native-offline-auth zustand @react-native-async-storage/async-storage
```

### Peer Dependencies

This library requires:
- `react` >= 18.0.0
- `react-native` >= 0.70.0
- `zustand` >= 4.0.0
- `@react-native-async-storage/async-storage` >= 1.17.0

## Quick Start

### 1. Wrap your app with AuthProvider

```tsx
import { AuthProvider } from '@loonylabs/react-native-offline-auth';
import App from './App';

export default function Root() {
  return (
    <AuthProvider
      apiCallbacks={{
        login: async (credentials) => {
          const response = await fetch('https://api.example.com/auth/login', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(credentials),
          });
          return response.json(); // { user, token }
        },
        register: async (credentials) => {
          const response = await fetch('https://api.example.com/auth/register', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(credentials),
          });
          return response.json(); // { user, token }
        },
        validateToken: async (token) => {
          const response = await fetch('https://api.example.com/auth/me', {
            headers: { Authorization: `Bearer ${token}` },
          });
          const data = await response.json();
          return data.user;
        },
      }}
    >
      <App />
    </AuthProvider>
  );
}
```

### 2. Use the hook in your components

```tsx
import { useAuth } from '@loonylabs/react-native-offline-auth';

function HomeScreen() {
  const {
    user,
    isAuthenticated,
    isGuestMode,
    login,
    logout,
    continueAsGuest,
  } = useAuth();

  if (isGuestMode) {
    return <Text>Welcome Guest! 👤</Text>;
  }

  if (isAuthenticated) {
    return (
      <View>
        <Text>Welcome {user.username}! 🔐</Text>
        <Button title="Logout" onPress={logout} />
      </View>
    );
  }

  return (
    <View>
      <Button title="Login" onPress={() => login({ email, password })} />
      <Button title="Continue as Guest" onPress={continueAsGuest} />
    </View>
  );
}
```

## Core Concepts

### Three Authentication States

1. **Authenticated** - User logged in with JWT token
2. **Guest Mode** - User using app without account (local data only)
3. **Unauthenticated** - User needs to login or continue as guest

### Offline-First Philosophy

- App starts **immediately** with cached credentials
- Token validation happens in background (non-blocking)
- Users stay logged in even when offline
- No forced logout on network errors

### Navigation Logic

```tsx
function RootNavigator() {
  const { isLoading, isAuthenticated, isGuestMode } = useAuth();

  if (isLoading) {
    return <SplashScreen />;
  }

  if (isAuthenticated || isGuestMode) {
    return <MainApp />;
  }

  return <AuthScreens />;
}
```

## Documentation

- **[Getting Started](docs/GETTING_STARTED.md)** - Step-by-step setup guide
- **[API Reference](docs/API.md)** - Complete API documentation
- **[Error Handling](docs/ERROR_HANDLING.md)** - Error handling guide
- **[Examples](docs/EXAMPLES.md)** - Common use cases and patterns
- **[Example App](example/)** - Full working example

## Key Features Explained

### Guest Mode

Allow users to try your app without registration:

```tsx
await continueAsGuest();
// User can now use the app with local-only data
```

### Upgrade to Account

Convert guest users to authenticated users:

```tsx
await upgradeToAccount({
  email: 'user@example.com',
  username: 'newuser',
  password: 'securepass123'
});
// Local data is preserved, now synced to cloud
```

### Offline Authentication

Users stay logged in when offline:

```tsx
// On app start:
// 1. Load token + user from AsyncStorage (instant)
// 2. Show app immediately
// 3. Validate token in background (when online)
// 4. Update user data if validation succeeds
// 5. Stay logged in even if validation fails (offline)
```

## Configuration

```tsx
<AuthProvider
  apiCallbacks={...}
  config={{
    // Custom storage keys (optional)
    storageKeys: {
      token: '@custom_token',
      user: '@custom_user',
      guestMode: '@custom_guest',
    },
    // Enable debug logging
    debug: true,
    // Custom token validator
    validateToken: async (token) => {
      // Your custom validation logic
      return user;
    },
    // Error callback
    onTokenValidationError: (error) => {
      console.log('Token validation failed:', error);
    },
  }}
  onReady={() => console.log('Auth initialized')}
>
  <App />
</AuthProvider>
```

## TypeScript Support

Fully typed with comprehensive TypeScript definitions:

```typescript
import type {
  User,
  AuthState,
  LoginCredentials,
  RegisterCredentials,
  AuthConfig,
} from '@loonylabs/react-native-offline-auth';
```

## Testing

The library includes test infrastructure:

```bash
npm test              # Run tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report
```

> **Note**: We're actively working on expanding test coverage. Contributions welcome!

## Architecture

```
┌─────────────────────────────────────────────┐
│           React Components                  │
│         (useAuth hook)                      │
└─────────────────┬───────────────────────────┘
                  │
┌─────────────────▼───────────────────────────┐
│         AuthProvider                        │
│    (Zustand Store + Context)                │
└─────────────────┬───────────────────────────┘
                  │
┌─────────────────▼───────────────────────────┐
│         AuthService                         │
│  (Business Logic + Validation)              │
└─────────────────┬───────────────────────────┘
                  │
┌─────────────────▼───────────────────────────┐
│         AuthStorage                         │
│      (AsyncStorage Wrapper)                 │
└─────────────────────────────────────────────┘
```

## Best Practices

### ✅ DO
- Use guest mode for better onboarding
- Load auth state on app start
- Handle offline scenarios gracefully
- Validate tokens in background
- Cache user data locally

### ❌ DON'T
- Wait for API calls on app start
- Logout users on network errors
- Block UI during token validation
- Store sensitive data beyond JWT token
- Force registration before trying the app

## Compatibility

- **React Native**: 0.70+
- **Expo**: ✅ Compatible (SDK 47+)
- **React Native Web**: ✅ Compatible
- **iOS**: ✅ Tested
- **Android**: ✅ Tested

## Contributing

Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.

## License

MIT © [LoonyLabs](https://github.com/loonylabs-dev)

## Support

- **Issues**: [GitHub Issues](https://github.com/loonylabs-dev/react-native-offline-auth/issues)
- **Discussions**: [GitHub Discussions](https://github.com/loonylabs-dev/react-native-offline-auth/discussions)

## Acknowledgments

Built with:
- [Zustand](https://github.com/pmndrs/zustand) - State management
- [AsyncStorage](https://github.com/react-native-async-storage/async-storage) - Persistent storage
- [TypeScript](https://www.typescriptlang.org/) - Type safety

---

**Made with ❤️ by [Loonylabs](https://github.com/loonylabs-dev)**