npm package: @jamx-framework/adapter-expo
Description: JAMX Framework â€” Expo / React Native adapter
Author: Stiven-21
Latest version: 2.0.0

# @jamx-framework/adapter-expo

## Descripción
Adaptador de JAMX Framework para Expo y React Native. Proporciona una API tipada y unificada que permite acceder a funcionalidades del ecosistema Expo (APIs, navegación, almacenamiento, tema, etc.) desde aplicaciones JAMX, manteniendo una arquitectura modular y compatible con TypeScript.

## Cómo funciona
El adaptador actúa como un puente entre JAMX y el ecosistema de Expo, ofreciendo servicios y managers que encapsulan APIs nativas de Expo. Todos los servicios están diseñados para ser utilizados mediante inyección de dependencias o instancias directas, y se integran con la arquitectura de JAMX mediante tipos e interfaces compartidas.

## Componentes principales
- **src/index.ts**: Punto de exportación que reúne todos los servicios
- **src/api.ts**: Cliente HTTP con interceptores, timeout y tipado de respuestas
- **src/config.ts**: Gestor de configuración de la aplicación (nombre, versión, API URL, entorno)
- **src/navigation.ts**: Gestor de navegación con stacks y rutas tipadas
- **src/storage.ts**: Adaptador de almacenamiento persistente (AsyncStorage)
- **src/theme.ts**: Gestor de tema con soporte para light/dark mode
- **src/types.ts**: Definiciones de tipos compartidos (AppConfig, NavigationRoute, etc.)

## Uso básico
```typescript
import {
  ExpoConfig,
  defineAppConfig,
  ExpoApiClient,
  createApiClient,
  NavigationManager,
  defineStack,
  defineRoute,
  ExpoStorageAdapter,
  TypedStorage,
  ThemeManager,
  defineTheme,
  DEFAULT_THEME,
} from '@jamx-framework/adapter-expo';

// Configurar la aplicación
const appConfig = defineAppConfig({
  name: 'MiAppJAMX',
  version: '1.0.0',
  apiUrl: 'https://api.miaplicacion.com',
  env: 'development',
});
ExpoConfig.init(appConfig);

// Crear cliente API
const api = createApiClient({ baseUrl: appConfig.apiUrl });
api.setAuthToken('mi-token-jwt');

// Hacer una petición
const response = await api.get('/users', { query: { limit: 10 } });
console.log('Usuarios:', response.data);

// Configurar navegación
const navigation = new NavigationManager();
navigation.addStack(
  defineStack({
    name: 'main',
    initialRoute: 'home',
    screens: [
      defineRoute({
        name: 'home',
        path: '/',
        component: HomeScreen,
      }),
      defineRoute({
        name: 'profile',
        path: '/profile/:id',
        component: ProfileScreen,
      }),
    ],
  }),
);
navigation.setActiveStack('main');

// Acceder a la ruta actual
const currentRoute = navigation.getActiveStack()?.screens[0];
console.log('Ruta actual:', currentRoute?.path);

// Usar almacenamiento persistente
const storage = new TypedStorage(new ExpoStorageAdapter());
await storage.set('user-settings', { theme: 'dark', language: 'es' });
const settings = await storage.get<{ theme: string; language: string }>('user-settings');
console.log('Configuración:', settings);

// Configurar tema
const themeManager = new ThemeManager(DEFAULT_THEME, 'dark');
themeManager.setScheme('dark');
const colors = themeManager.getColors();
console.log('Color primario:', colors.primary);
```

## Ejemplos
### Cliente API con interceptores
```typescript
import { createApiClient, ExpoApiClient } from '@jamx-framework/adapter-expo';

const api = createApiClient({
  baseUrl: 'https://api.miaplicacion.com',
  timeout: 5000,
});

api.addRequestInterceptor(config => {
  config.headers = {
    ...config.headers,
    'x-client': 'JAMX-Web',
  };
  return config;
});

api.addResponseInterceptor(response => {
  if (response.status >= 400) {
    console.error('Error API:', response.data);
  }
  return response;
});

const response = await api.post('/login', { email: 'user@example.com', password: 'secret' });
console.log('Token:', response.data.token);
```

### Navegación con stacks anidados
```typescript
import { NavigationManager, defineStack, defineRoute } from '@jamx-framework/adapter-expo';

const navigation = new NavigationManager();

navigation.addStack(
  defineStack({
    name: 'app',
    screens: [
      defineRoute({
        name: 'tabs',
        path: '/*',
        component: TabsScreen,
      }),
      defineRoute({
        name: 'login',
        path: 'login',
        component: LoginScreen,
      }),
      defineRoute({
        name: 'detail',
        path: 'item/:id',
        component: ItemDetailScreen,
      }),
    ],
  }),
);

navigation.setActiveStack('app');
const tabsRoute = navigation.getRoute('app', 'tabs');
console.log('Ruta de tabs:', tabsRoute?.path);
```

### Almacenamiento tipado
```typescript
import { TypedStorage, ExpoStorageAdapter } from '@jamx-framework/adapter-expo';

interface UserSettings {
  theme: 'light' | 'dark';
  language: string;
  notifications: boolean;
}

const storage = new TypedStorage(new ExpoStorageAdapter());
const settings: UserSettings = { theme: 'dark', language: 'es', notifications: true };
await storage.set('user-settings', settings);
const loaded = await storage.get<UserSettings>('user-settings');
console.log('Ajustes cargados:', loaded);
```

### Gestión de tema global
```typescript
import { ThemeManager, defineTheme, DEFAULT_THEME } from '@jamx-framework/adapter-expo';

const theme = new ThemeManager(defineTheme({ light: { primary: '#0066ff' } }), 'light');
theme.setScheme('dark');
const primary = theme.get('primary');
console.log('Color primario en dark mode:', primary);
```

## Flujo interno
1. **Inicialización**: `ExpoConfig.init()` carga la configuración y la hace disponible globalmente.
2. **Servicios**: Cada componente (API, navegación, almacenamiento, tema) se instancia y se registra en el contenedor de dependencias de JAMX.
3. **Intercepción**: El `ExpoApiClient` permite agregar interceptores para modificar requests/responses antes/despues de enviarlas.
4. **Navegación**: `NavigationManager` gestiona stacks de navegación y permite registrar rutas con tipos completos.
5. **Persistencia**: `TypedStorage` proporciona acceso tipado a AsyncStorage con serialización/deserialización automática.
6. **Tema**: `ThemeManager` gestiona esquemas de color y permite cambiar entre light/dark mode dinámicamente.
7. **Integración**: Todos los servicios pueden ser inyectados en cualquier parte de la aplicación mediante el contenedor de JAMX, garantizando un acoplamiento bajo y una prueba fácil.

## API Reference (Resumen)
### ExpoConfig
- `static init(config: AppConfig): ExpoConfig`
- `static get(): ExpoConfig`
- `getApiEndpoint(path: string): string`

### ExpoApiClient
- `setAuthToken(token: string | null): void`
- `addRequestInterceptor(fn: (config) => config): void`
- `addResponseInterceptor(fn: (res) => res): void`
- `get<T>(path: string, params?: Record<string, string>): Promise<ApiResponse<T>>`
- `post<T>(path: string, body?: unknown): Promise<ApiResponse<T>>`
- `...` (put, patch, delete)

### NavigationManager
- `addStack(stack: NavigationStack): void`
- `getStack(name: string): NavigationStack | null`
- `setActiveStack(name: string): void`
- `getRoute(stackName: string, routeName: string): NavigationRoute | null`

### TypedStorage
- `get<K>(key: K): Promise<Schema[K] | null>`
- `set<K>(key: K, value: Schema[K]): Promise<void>`
- `remove<K>(key: K): Promise<void>`
- `clear(): Promise<void>`

### ThemeManager
- `setScheme(scheme: ColorSchemeName): void`
- `getScheme(): ColorSchemeName`
- `getColors(): ThemeColors`
- `get(key: keyof ThemeColors): string`
- `isDark(): boolean`
- `isLight(): boolean`

## Performance Considerations
- **Network Efficiency**: Todos los requests usan `fetch` con abort controllers y timeout configurables.
- **Almacenamiento en Memoria**: Las operaciones de AsyncStorage están encapsuladas para minimizar accesos a la API nativa.
- **Tema Reactivo**: Los cambios de tema se reflejan inmediatamente en la UI sin re-renders costosos.
- **Inyección de Dependencias**: El contenedor evita la creación innecesaria de instancias mediante caché de singletons.

## Configuration Options
```typescript
// app.config.ts
export default defineAppConfig({
  name: 'MiAplicación',
  version: '1.0.0',
  scheme: 'myapp',
  apiUrl: 'https://api.miaplicacion.com',
  env: 'development',
});
```

## Testing
El proyecto incluye tests unitarios en `packages/adapter-expo/tests/unit/`. Para ejecutarlos:

```bash
pnpm test
# o
npm run test
```

Los tests cubren:
- Configuración inicial y carga de AppConfig
- Funcionalidad del cliente API con interceptores
- Gestión de navegación y registro de rutas
- Almacenamiento tipado y serialización
- Cambios de tema y detección de esquema de color
- Integración con el contenedor de dependencias de JAMX

## Compatibility
- Compatible con Expo SDK >= 50.0.0
- Funciona en React Native >= 0.73.0
- Soporta plataformas: iOS, Android, Web
- No requiere dependencias globales; todas las herramientas se instalan como devDependencies

## CLI Integration
Este adaptador se integra automáticamente con el CLI de JAMX:
- `jamx build`: Compila los archivos de adaptador a `dist/`.
- `jamx dev`: Inicia un entorno de desarrollo que simula el bootstrap de Expo.
- `jamx config:validate`: Verifica que `app.config.ts` tenga la estructura esperada.

This adapter provides a seamless bridge between JAMX Framework and Expo, enabling developers to build universal applications with a single codebase while maintaining full type safety and access to native Expo capabilities.