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

@mp-front/common

v0.0.3

Published

Una librería integral de TypeScript para aplicaciones frontend con autenticación, caché, cliente HTTP y utilidades de middleware construida con RxJS y patrones modernos.

Readme

@mp-front/common

Una librería integral de TypeScript para aplicaciones frontend con autenticación, caché, cliente HTTP y utilidades de middleware construida con RxJS y patrones modernos.

Comenzando

Instalación

npm install @mp-front/common

Dependencias Peer

npm install [email protected] [email protected] [email protected] [email protected]

Inicio Rápido

import { HttpClient } from '@mp-front/common/http'
import { Logger } from '@mp-front/common/helpers'

const client = new HttpClient()
const logger = new Logger()

client.get('/api/users').subscribe(users => {
  logger.logInfo('Usuarios cargados', JSON.stringify(users))
})

Arquitectura

La librería sigue una arquitectura modular que permite tree-shaking e importaciones selectivas:

@mp-front/common/
├── auth              # Servicios de autenticación
├── engine            # Integración con Azure Entra ID
├── http              # Cliente HTTP con RxJS
├── cache             # Caché de sesión y terminal
├── cache-providers   # Implementación de caché Redis
├── helpers           # Utilidades (Logger, Encoder, Encrypter)
├── errors            # Sistema de manejo de errores
├── rxjs              # Utilidades y manejadores RxJS
├── middleware        # Middleware de API para Next.js
└── adapters          # Adaptadores NextAuth

Referencia de API

Autenticación

AuthorizationService

Servicio para autenticación de tokens del backend.

import { AuthorizationService } from '@mp-front/common/auth'

const authService = new AuthorizationService()

authService.get().subscribe({
  next: token => console.log('Token:', token),
  error: error => console.error('Error de auth:', error)
})

Variables de Entorno:

API_AUTH_BACK_URL=https://api.example.com/auth
API_AUTH_BACK_USERNAME_AUTH=username
API_AUTH_BACK_PASSWORD_AUTH=password
ID_FRONT=frontend-app-id

Motor Azure

AuthEngine

Integración con Azure Entra ID para verificación de roles y grupos.

import { AuthEngine } from '@mp-front/common/engine'

const authEngine = new AuthEngine()

// Verificar roles de usuario
authEngine.getRoles('[email protected]', 'app-object-id').subscribe({
  next: ({ roles }) => console.log('Roles del usuario:', roles)
})

// Verificar rol específico
authEngine.inRole('[email protected]', 'role-id', 'app-object-id').subscribe({
  next: hasRole => console.log('Tiene rol:', hasRole)
})

// Verificar membresía de grupo
authEngine.inGroup('[email protected]', 'group-id').subscribe({
  next: inGroup => console.log('En grupo:', inGroup)
})

Variables de Entorno:

AZURE_AD_GRAPH_GET_APP_ROLES=https://graph.microsoft.com/v1.0/applications/{id-obj}/appRoles
AZURE_AD_GRAPH_GET_USER_BY_EMAIL=https://graph.microsoft.com/v1.0/users/{user-mail}
AZURE_AD_GRAPH_GROUPS=https://graph.microsoft.com/v1.0/users/idUser/memberOf

Cliente HTTP

HttpClient

Cliente HTTP basado en RxJS con estados de carga automáticos y manejo de errores.

import { HttpClient } from '@mp-front/common/http'

const client = new HttpClient()

// Petición GET
client.get<User[]>('/api/users', {
  params: { page: 1, limit: 10 },
  headers: { 'Authorization': 'Bearer token' }
}).subscribe(users => {
  console.log('Usuarios:', users)
})

// Petición POST
client.post<User>('/api/users', {
  name: 'Juan Pérez',
  email: '[email protected]'
}).subscribe(newUser => {
  console.log('Creado:', newUser)
})

// Deshabilitar carga global
client.setIsLoadingEnabled(false)

Métodos:

  • get<T>(url, options?) - Petición GET
  • post<T>(url, body, options?) - Petición POST
  • put<T>(url, body, options?) - Petición PUT
  • patch<T>(url, body, options?) - Petición PATCH
  • delete<T>(url, options?) - Petición DELETE

Gestión de Caché

SessionCache

Gestión de sesiones de usuario con Redis.

import { SessionCache } from '@mp-front/common/cache'

const sessionCache = new SessionCache('user-id-123')

// Obtener sesión básica
const session = await sessionCache.getBasicSession()
console.log('Usuario:', session.user)

// Obtener sesión completa con datos de tienda
const fullSession = await sessionCache.getUserAndShoppingStore()

TerminalCache

Gestión de datos de terminal.

import { TerminalCache } from '@mp-front/common/cache'

const terminalCache = new TerminalCache()

// Establecer datos de terminal
await terminalCache.set('SELLER001', {
  terminalId: 'TERM123',
  location: 'Tienda A',
  status: 'active'
})

// Obtener datos de terminal
const terminal = await terminalCache.get('SELLER001')

// Eliminar datos de terminal
await terminalCache.delete('SELLER001')

Proveedores de Caché

RedisCache

Proveedor genérico de caché Redis con soporte de encriptación.

import { RedisCache } from '@mp-front/common/cache-providers'

interface UserData {
  name: string
  email: string
}

const redis = new RedisCache<UserData>()

// Establecer datos con encriptación
await redis.set({
  prefix: 'user:123',
  idData: 'profile',
  body: { name: 'Juan', email: '[email protected]' },
  expire: 3600,
  encrypted: true
})

// Obtener datos
const { data, sha } = await redis.get<UserData>('user:123', 'profile')

// Eliminar datos
await redis.delete('user:123', 'profile')

// Operaciones simples
const value = await redis.simpleGet('key')
await redis.simpleHSet('hash-key', 'field', 'value')
const allFields = await redis.simpleHGetAll('hash-key')

Variables de Entorno:

REDIS_URL=redis://localhost:6379
TIMEOUT_SESSION_MINUTES=60
SECRET_SIGNATURE=tu-clave-secreta-min-32-chars

Utilidades

Logger

Logging estructurado con niveles y colores.

import { Logger } from '@mp-front/common/helpers'

const logger = new Logger()

logger.logError('Error crítico', JSON.stringify(error))
logger.logWarn('Uso de API deprecada')
logger.logInfo('Usuario autenticado exitosamente')
logger.logDebug('Datos de petición:', JSON.stringify(data))

Niveles de Log: error, warn, info, http, verbose, debug, silly

Variables de Entorno:

NEXT_PUBLIC_APP_LOGS_NAME=MiApp
NEXT_PUBLIC_LOGS_LEVEL=debug
NEXT_PUBLIC_SILENT_LOGS=false

Encoder

Codificación/decodificación Base64 para datos de API.

import { Encoder } from '@mp-front/common/helpers'

const encoder = new Encoder()

// Codificar datos
const encoded = encoder.encode({ name: 'Juan' }, 'request-id-123')
// Resultado: { info: 'base64...', requestID: 'request-id-123' }

// Decodificar datos
const decoded = encoder.decode(encoded)
// Resultado: { name: 'Juan' }

Encrypter

Encriptación/desencriptación JWE con node-jose.

import { Encrypter } from '@mp-front/common/helpers'

const encrypter = new Encrypter()

// Encriptar datos sensibles
const encrypted = await encrypter.encrypt({
  password: 'secret123',
  apiKey: 'key-xyz'
})

// Desencriptar datos
const decrypted = await encrypter.decrypt(encrypted)

// Verificar si los datos están encriptados
const isEncrypted = await encrypter.isEncrypted(someString)

// Generar hash SHA256
const sha = encrypter.generateSHA({ userId: '123' })

Manejo de Errores

ErrorHandler

Gestión global de errores con patrón Singleton.

import { ErrorHandler } from '@mp-front/common/errors'

// Suscribirse a errores globales
ErrorHandler.getInstance().getSubject().subscribe(error => {
  console.error('Error global:', error)
  showNotification({
    type: 'error',
    message: error.message,
    code: error.code
  })
})

RuntimeError

Clase de error personalizada con seguimiento de peticiones.

import { RuntimeError, RuntimeErrorCode } from '@mp-front/common/errors'

// Lanzar error personalizado
throw new RuntimeError(RuntimeErrorCode.VALIDATION_ERROR, 'request-id-123')

// En bloques catch
try {
  // código
} catch (error) {
  throw new RuntimeError('CUSTOM_ERROR', requestId)
}

Utilidades RxJS

LoadingHandler

Gestión global del estado de carga.

import { LoadingHandler } from '@mp-front/common/rxjs'

// Suscribirse al estado de carga
LoadingHandler.getInstance().getSubject().subscribe(isLoading => {
  if (isLoading) {
    showSpinner()
  } else {
    hideSpinner()
  }
})

// Controlar carga manualmente
LoadingHandler.getInstance().setSubject(true)  // Mostrar carga
LoadingHandler.getInstance().setSubject(false) // Ocultar carga

Integración con React:

import { useEffect, useState } from 'react'
import { LoadingHandler } from '@mp-front/common/rxjs'

function App() {
  const [isLoading, setIsLoading] = useState(false)

  useEffect(() => {
    const subscription = LoadingHandler.getInstance()
      .getSubject()
      .subscribe(setIsLoading)

    return () => subscription.unsubscribe()
  }, [])

  return (
    <>
      {isLoading && <Spinner />}
      {/* resto de la app */}
    </>
  )
}

Middleware

ApiMiddleware

Middleware de API para Next.js con codificación/decodificación automática.

import { ApiMiddleware } from '@mp-front/common/middleware'
import { of } from 'rxjs'

interface CreateUserRequest {
  name: string
  email: string
}

interface CreateUserResponse {
  id: string
  name: string
  email: string
}

class UserApiMiddleware extends ApiMiddleware {
  createUser = this.get<CreateUserRequest, CreateUserResponse>(
    (params, { requestID, headers }) => {
      // Validación
      if (!params.name || !params.email) {
        throw new RuntimeError('VALIDATION_ERROR', requestID)
      }

      // Obtener sesión
      const session = this.getSession()

      // Lógica de negocio
      const newUser = {
        id: generateId(),
        name: params.name,
        email: params.email
      }

      return of(newUser)
    }
  )
}

export const POST = new UserApiMiddleware().createUser

Manejador de Subida de Archivos:

export const POST = middleware.getFormData<ResponseType>(
  (params, files) => {
    // Procesar archivos
    return of({
      uploadedFiles: files.map(f => ({
        name: f.name,
        size: f.size
      }))
    })
  }
)

Adaptadores

IORedisAdapter

Adaptador NextAuth para Redis.

import { IORedisAdapter } from '@mp-front/common/adapters'

export const authOptions = {
  adapter: IORedisAdapter({
    expire: 3600 // segundos
  }),
  // ... otras opciones de NextAuth
}

Configuración

Variables de Entorno

Crea un archivo .env.local con las siguientes variables:

# Logging
NEXT_PUBLIC_APP_LOGS_NAME=MiApp
NEXT_PUBLIC_LOGS_LEVEL=debug
NEXT_PUBLIC_SILENT_LOGS=false

# Backend de Autenticación
API_AUTH_BACK_URL=https://api.example.com/auth
API_AUTH_BACK_USERNAME_AUTH=username
API_AUTH_BACK_PASSWORD_AUTH=password
ID_FRONT=frontend-app-id

# Azure Entra ID
AZURE_AD_GRAPH_GET_APP_ROLES=https://graph.microsoft.com/v1.0/applications/{id-obj}/appRoles
AZURE_AD_GRAPH_GET_USER_BY_EMAIL=https://graph.microsoft.com/v1.0/users/{user-mail}
AZURE_AD_GRAPH_GROUPS=https://graph.microsoft.com/v1.0/users/idUser/memberOf

# Redis
REDIS_URL=redis://localhost:6379
TIMEOUT_SESSION_MINUTES=60
PREFIX_LOGIN=app

# Encriptación
SECRET_SIGNATURE=tu-clave-secreta-min-32-chars

Ejemplos

Sistema de Autenticación Completo

import { AuthorizationService } from '@mp-front/common/auth'
import { HttpClient } from '@mp-front/common/http'
import { SessionCache } from '@mp-front/common/cache'
import { firstValueFrom } from 'rxjs'

class AuthSystem {
  private authService = new AuthorizationService()
  private httpClient = new HttpClient()
  private sessionCache: SessionCache

  async login(userId: string) {
    // Obtener token
    const token = await firstValueFrom(this.authService.get())

    // Configurar sesión
    this.sessionCache = new SessionCache(userId)
    const session = await this.sessionCache.getBasicSession()

    // Hacer petición autenticada
    this.httpClient.get('/api/protected', {
      headers: { Authorization: `Bearer ${token}` }
    }).subscribe(data => {
      console.log('Datos protegidos:', data)
    })
  }
}

Sistema de Caché Multi-nivel

import { RedisCache } from '@mp-front/common/cache-providers'

class CacheSystem<T> {
  private redis = new RedisCache<T>()
  private memoryCache = new Map<string, T>()

  async get(key: string): Promise<T | null> {
    // Nivel 1: Memoria
    if (this.memoryCache.has(key)) {
      return this.memoryCache.get(key)!
    }

    // Nivel 2: Redis
    try {
      const { data } = await this.redis.get<T>(key, 'data')
      this.memoryCache.set(key, data)
      return data
    } catch {
      return null
    }
  }

  async set(key: string, value: T, ttl: number = 3600) {
    this.memoryCache.set(key, value)
    
    await this.redis.set({
      prefix: key,
      idData: 'data',
      body: value,
      expire: ttl,
      encrypted: true
    })
  }
}

Sistema Global de Errores

import { ErrorHandler, RuntimeError } from '@mp-front/common/errors'
import { LoadingHandler } from '@mp-front/common/rxjs'

class GlobalErrorSystem {
  constructor() {
    this.setupErrorHandling()
  }

  private setupErrorHandling() {
    ErrorHandler.getInstance().getSubject().subscribe(error => {
      // Ocultar carga
      LoadingHandler.getInstance().setSubject(false)

      // Registrar error
      console.error('Error:', error)

      // Mostrar notificación
      this.showErrorNotification(error)
    })
  }

  private showErrorNotification(error: RuntimeError) {
    // La implementación depende de tu sistema de notificaciones
  }
}

Mejores Prácticas

Gestión de Suscripciones RxJS

import { Component, OnDestroy } from '@angular/core'
import { Subject, takeUntil } from 'rxjs'

class MyComponent implements OnDestroy {
  private destroy$ = new Subject<void>()

  ngOnInit() {
    this.httpClient.get('/api/data')
      .pipe(takeUntil(this.destroy$))
      .subscribe(data => {
        // Procesar datos
      })
  }

  ngOnDestroy() {
    this.destroy$.next()
    this.destroy$.complete()
  }
}

Seguridad de Tipos

// Definir interfaces
interface User {
  id: string
  name: string
  email: string
}

// Usar tipos genéricos
const redis = new RedisCache<User>()
const client = new HttpClient()

client.get<User>('/api/user/1').subscribe(user => {
  // TypeScript sabe que user es de tipo User
  console.log(user.name)
})

Manejo de Errores

import { catchError, of } from 'rxjs'

client.get<Data>('/api/data')
  .pipe(
    catchError(error => {
      console.error('Error:', error)
      return of(null) // Valor por defecto
    })
  )
  .subscribe(data => {
    if (data) {
      // Procesar datos
    }
  })

Solución de Problemas

Problemas de Conexión Redis

import { RedisCache } from '@mp-front/common/cache-providers'

const redis = new RedisCache()

redis.statusHost()
  .then(() => console.log('Redis conectado'))
  .catch(error => console.error('Error de conexión:', error))

Los Logs No Aparecen

Verifica estas variables de entorno:

  1. NEXT_PUBLIC_SILENT_LOGS=false
  2. NEXT_PUBLIC_LOGS_LEVEL está configurado correctamente
  3. El nivel de log es apropiado para tus mensajes

Fallas de Encriptación

Verifica:

  1. SECRET_SIGNATURE está definido en .env
  2. La clave tiene al menos 32 caracteres
  3. Se usa la misma clave para operaciones de encriptar/desencriptar

Guía de Migración

De v0.0.1 a v0.0.2

  • Actualiza las rutas de importación para usar importaciones modulares
  • Reemplaza métodos deprecados con la nueva API
  • Actualiza nombres de variables de entorno

Contribuir

  1. Haz fork del repositorio
  2. Crea una rama de feature
  3. Realiza tus cambios
  4. Agrega pruebas
  5. Envía un pull request

Licencia

Privado - Solo uso interno