@jamx-framework/adapter-expo
v2.0.0
Published
JAMX Framework — Expo / React Native adapter
Downloads
125
Maintainers
Readme
@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
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
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: '[email protected]', password: 'secret' });
console.log('Token:', response.data.token);Navegación con stacks anidados
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
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
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
- Inicialización:
ExpoConfig.init()carga la configuración y la hace disponible globalmente. - Servicios: Cada componente (API, navegación, almacenamiento, tema) se instancia y se registra en el contenedor de dependencias de JAMX.
- Intercepción: El
ExpoApiClientpermite agregar interceptores para modificar requests/responses antes/despues de enviarlas. - Navegación:
NavigationManagergestiona stacks de navegación y permite registrar rutas con tipos completos. - Persistencia:
TypedStorageproporciona acceso tipado a AsyncStorage con serialización/deserialización automática. - Tema:
ThemeManagergestiona esquemas de color y permite cambiar entre light/dark mode dinámicamente. - 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): ExpoConfigstatic get(): ExpoConfiggetApiEndpoint(path: string): string
ExpoApiClient
setAuthToken(token: string | null): voidaddRequestInterceptor(fn: (config) => config): voidaddResponseInterceptor(fn: (res) => res): voidget<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): voidgetStack(name: string): NavigationStack | nullsetActiveStack(name: string): voidgetRoute(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): voidgetScheme(): ColorSchemeNamegetColors(): ThemeColorsget(key: keyof ThemeColors): stringisDark(): booleanisLight(): boolean
Performance Considerations
- Network Efficiency: Todos los requests usan
fetchcon 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
// 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:
pnpm test
# o
npm run testLos 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 adist/.jamx dev: Inicia un entorno de desarrollo que simula el bootstrap de Expo.jamx config:validate: Verifica queapp.config.tstenga 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.
