npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jamx-framework/adapter-expo

v2.0.0

Published

JAMX Framework — Expo / React Native adapter

Downloads

125

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

  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

// 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 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.