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>
4.8 KiB
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-storefor secure token storage andAsyncStoragefor local data - Web: Uses browser
localStoragefor all storage needs
File Uploads
- Mobile: Uses
expo-file-systemFile API to read files and convert to base64 - Web: Uses browser
FileAPI andFileReaderto convert files to base64
Crypto
- Mobile: Uses
react-native-get-random-valuespolyfill 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→localStorageexpo-file-system→FileReader APIreact-native-get-random-values→ nativecrypto
Usage
Basic Authentication
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
// 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
// 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:
interface ApiResponse<T> {
data?: T;
error?: ApiError;
ok: boolean;
}
interface ApiError {
message: string;
code?: string;
status?: number;
}
Example error handling:
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:
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:
import type { Beneficiary, User, ApiResponse } from '@/types';
Testing
Tests are located in __tests__/lib/api.test.ts.
Run tests:
npm test
Run specific test file:
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)fetchAPI (all modern browsers)FileReaderAPI (all modern browsers)
No polyfills required for target browsers (Chrome 70+, Edge 79+, Opera 57+).