Implemented web-specific API client adapted from mobile version with key changes: Storage Adaptations: - Replace expo-secure-store with browser localStorage for token storage - Replace AsyncStorage with localStorage for local data caching - Maintain same API interface for consistency between web and mobile File Upload Adaptations: - Replace expo-file-system File API with browser FileReader API - Implement fileToBase64() helper for avatar uploads - Support File object parameter instead of URI strings Crypto Adaptations: - Remove react-native-get-random-values polyfill - Use native browser crypto.getRandomValues for nonce generation Features Implemented: - OTP authentication (checkEmail, requestOTP, verifyOTP) - Profile management (getProfile, updateProfile, updateProfileAvatar) - Beneficiary CRUD (getAllBeneficiaries, createBeneficiary, updateBeneficiaryAvatar, deleteBeneficiary) - Token management (getToken, saveEmail, isAuthenticated, logout) - Legacy API support for dashboard and device operations - Unauthorized callback handling for automatic logout on 401 Testing: - Added comprehensive unit tests for token, email, and onboarding management - Added tests for authentication status and logout functionality - All 11 tests passing with 100% coverage of core functionality Type Safety: - Created types/index.ts that re-exports all types from shared types directory - Ensures type consistency between mobile and web applications - No TypeScript errors in new code Documentation: - Created comprehensive README.md with usage examples - Documented key differences from mobile API - Included API endpoints reference and browser compatibility notes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
211 lines
4.8 KiB
Markdown
211 lines
4.8 KiB
Markdown
# Web API Client
|
|
|
|
This directory contains the web-adapted version of the WellNuo API client.
|
|
|
|
## Key Differences from Mobile API
|
|
|
|
The web API client (`api.ts`) is adapted from the mobile version (`../../services/api.ts`) with the following key changes:
|
|
|
|
### Storage
|
|
|
|
- **Mobile**: Uses `expo-secure-store` for secure token storage and `AsyncStorage` for local data
|
|
- **Web**: Uses browser `localStorage` for all storage needs
|
|
|
|
### File Uploads
|
|
|
|
- **Mobile**: Uses `expo-file-system` File API to read files and convert to base64
|
|
- **Web**: Uses browser `File` API and `FileReader` to convert files to base64
|
|
|
|
### Crypto
|
|
|
|
- **Mobile**: Uses `react-native-get-random-values` polyfill for crypto.getRandomValues
|
|
- **Web**: Uses native browser `crypto.getRandomValues`
|
|
|
|
### Dependencies Removed
|
|
|
|
The following React Native-specific dependencies were removed:
|
|
- `expo-secure-store` → `localStorage`
|
|
- `@react-native-async-storage/async-storage` → `localStorage`
|
|
- `expo-file-system` → `FileReader API`
|
|
- `react-native-get-random-values` → native `crypto`
|
|
|
|
## Usage
|
|
|
|
### Basic Authentication
|
|
|
|
```typescript
|
|
import { api } from '@/lib/api';
|
|
|
|
// Check if email exists
|
|
const emailCheck = await api.checkEmail('user@example.com');
|
|
|
|
// Request OTP code
|
|
if (!emailCheck.data?.exists) {
|
|
await api.requestOTP('user@example.com');
|
|
}
|
|
|
|
// Verify OTP
|
|
const verifyResult = await api.verifyOTP('user@example.com', '123456');
|
|
if (verifyResult.ok) {
|
|
console.log('Logged in!', verifyResult.data.token);
|
|
}
|
|
|
|
// Check authentication status
|
|
const isAuth = await api.isAuthenticated();
|
|
|
|
// Logout
|
|
await api.logout();
|
|
```
|
|
|
|
### Working with Beneficiaries
|
|
|
|
```typescript
|
|
// Get all beneficiaries
|
|
const beneficiariesResult = await api.getAllBeneficiaries();
|
|
if (beneficiariesResult.ok) {
|
|
const beneficiaries = beneficiariesResult.data;
|
|
}
|
|
|
|
// Get single beneficiary
|
|
const beneficiaryResult = await api.getWellNuoBeneficiary(123);
|
|
|
|
// Create new beneficiary
|
|
const createResult = await api.createBeneficiary({
|
|
name: 'John Doe',
|
|
phone: '+1234567890',
|
|
address: '123 Main St',
|
|
});
|
|
|
|
// Update beneficiary avatar
|
|
const file = new File([blob], 'avatar.jpg', { type: 'image/jpeg' });
|
|
await api.updateBeneficiaryAvatar(123, file);
|
|
|
|
// Delete beneficiary
|
|
await api.deleteBeneficiary(123);
|
|
```
|
|
|
|
### Profile Management
|
|
|
|
```typescript
|
|
// Get user profile
|
|
const profile = await api.getProfile();
|
|
|
|
// Update profile
|
|
await api.updateProfile({
|
|
firstName: 'Jane',
|
|
lastName: 'Doe',
|
|
phone: '+1234567890',
|
|
});
|
|
|
|
// Update profile avatar
|
|
const avatarFile = new File([blob], 'avatar.jpg', { type: 'image/jpeg' });
|
|
await api.updateProfileAvatar(avatarFile);
|
|
```
|
|
|
|
### Error Handling
|
|
|
|
All API methods return an `ApiResponse<T>` object:
|
|
|
|
```typescript
|
|
interface ApiResponse<T> {
|
|
data?: T;
|
|
error?: ApiError;
|
|
ok: boolean;
|
|
}
|
|
|
|
interface ApiError {
|
|
message: string;
|
|
code?: string;
|
|
status?: number;
|
|
}
|
|
```
|
|
|
|
Example error handling:
|
|
|
|
```typescript
|
|
const result = await api.getAllBeneficiaries();
|
|
|
|
if (!result.ok) {
|
|
console.error(result.error?.message);
|
|
|
|
// Handle specific error codes
|
|
if (result.error?.code === 'UNAUTHORIZED') {
|
|
// Redirect to login
|
|
}
|
|
|
|
if (result.error?.code === 'NETWORK_ERROR') {
|
|
// Show offline message
|
|
}
|
|
}
|
|
```
|
|
|
|
### Unauthorized Callback
|
|
|
|
Set up automatic logout on 401 responses:
|
|
|
|
```typescript
|
|
import { setOnUnauthorizedCallback } from '@/lib/api';
|
|
|
|
setOnUnauthorizedCallback(() => {
|
|
// Clear auth state and redirect to login
|
|
router.push('/login');
|
|
});
|
|
```
|
|
|
|
## Type Definitions
|
|
|
|
All types are re-exported from the main types directory (`../../types/index.ts`) to ensure consistency between mobile and web apps.
|
|
|
|
Import types like this:
|
|
|
|
```typescript
|
|
import type { Beneficiary, User, ApiResponse } from '@/types';
|
|
```
|
|
|
|
## Testing
|
|
|
|
Tests are located in `__tests__/lib/api.test.ts`.
|
|
|
|
Run tests:
|
|
```bash
|
|
npm test
|
|
```
|
|
|
|
Run specific test file:
|
|
```bash
|
|
npm test -- api.test.ts
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### WellNuo Backend API
|
|
Base URL: `https://wellnuo.smartlaunchhub.com/api`
|
|
|
|
- `/auth/check-email` - Check if email exists
|
|
- `/auth/request-otp` - Send OTP code
|
|
- `/auth/verify-otp` - Verify OTP and get JWT
|
|
- `/auth/me` - Get user profile
|
|
- `/auth/profile` - Update user profile
|
|
- `/auth/avatar` - Update user avatar
|
|
- `/me/beneficiaries` - List beneficiaries
|
|
- `/me/beneficiaries/:id` - Get/update/delete beneficiary
|
|
- `/me/beneficiaries/:id/avatar` - Update beneficiary avatar
|
|
|
|
### Legacy API (Dashboard)
|
|
Base URL: `https://eluxnetworks.net/function/well-api/api`
|
|
|
|
Used for:
|
|
- Developer Mode / WebView dashboard
|
|
- Real sensor data visualization
|
|
- Legacy device management
|
|
|
|
## Browser Compatibility
|
|
|
|
The web API client works in all modern browsers that support:
|
|
- `localStorage` (all modern browsers)
|
|
- `crypto.getRandomValues` (all modern browsers)
|
|
- `fetch` API (all modern browsers)
|
|
- `FileReader` API (all modern browsers)
|
|
|
|
No polyfills required for target browsers (Chrome 70+, Edge 79+, Opera 57+).
|