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

v1.0.0

Published

JAMX Framework — Core IoC Container and Utilities

Readme

@jamjx-framework/core

Descripción

Núcleo de JAMX Framework: contenedor de Inversión de Control (IoC), utilidades básicas, decoradores, bootstrap y sistemas de plugins. Este paquete provee la infraestructura fundamental que permite la modularidad, la inyección de dependencias y la arquitectura de extensibilidad de JAMX. Es el pilar sobre el cual se construyen todos los demás módulos del framework.

Cómo funciona

El núcleo de JAMX está diseñado alrededor de tres conceptos clave:

  1. Container: Sistema de registro y resolución de dependencias con soporte para scopes (singleton, transient, scoped) y detección de dependencias circulares.
  2. Decorators: @injectable(), @inject() y @module() que permiten marcar clases y métodos para que el contenedor los gestione automáticamente.
  3. Bootstrap: Función bootstrap() que inicia la aplicación, carga configuración, inicializa módulos y arranca servidores de manera ordenada.

Además, el núcleo incluye utilidades para:

  • Generación de documentación (DocGenerator)
  • Manejo de excepciones (HttpException y subclasses)
  • Registro de plugins (PluginRegistry)
  • Tipos y utilidades comunes (Result, PaginationOptions, Brand, etc.)

Componentes principales

  • src/container/container.ts: Clase Container que gestiona el registro y resolución de dependencias.
  • src/container/decorators.ts: Decoradores @injectable() y @inject() para marcar clases y parámetros.
  • src/container/tokens.ts: Definiciones de Token, InjectionToken y tokenKey() para identificar dependencias.
  • src/bootstrap/app.ts: Función bootstrap() que orquesta el arranque de la aplicación.
  • src/docs/doc-generator.ts: Clase DocGenerator para generar documentación en Markdown y OpenAPI.
  • src/exceptions/http.ts: Jerarquía de excepciones HTTP (BadRequestException, UnauthorizedException, etc.).
  • src/module/module.ts: Decorador @module() para definir módulos y sus dependencias.
  • src/plugins/registry.ts: PluginRegistry para gestionar plugins con dependencias y ciclo de vida.
  • src/types/common.ts: Tipos compartidos como Result, PaginationOptions, Brand, etc.
  • src/index.ts: Punto de exportación que reúne todos los componentes del núcleo.

Uso básico

import { Container, token, injectable, inject } from '@jamx-framework/core';

// Definir tokens
const DB_TOKEN = token<Database>('Database');

// Clase inyectable
@injectable()
class Database {
  constructor(@inject(DB_TOKEN) private driver: DatabaseDriver) {}
}

// Registrar en el contenedor global
Container.registerClass(Database);

// Resolver dependencias
const db = Container.resolve(Database);

Registro de servicios

// Registrar una clase como singleton
Container.registerClass(UserRepository);

// Registrar un valor directo
const CONFIG_TOKEN = token<Config>('Config');
Container.register(COFIG_TOKEN, { useValue: myConfig });

// Registrar una fábrica
Container.registerClass(Logger, [Database], 'singleton');

Inyección de dependencias

@injectable()
class UsersService {
  constructor(@inject(UserRepository) private repo: UserRepository) {}

  async findAll() {
    return this.repo.findAll();
  }
}

// Al resolver UsersService, el contenedor inyecta automáticamente UserRepository
const service = Container.resolve(UsersService);

Módulos

@module({
  imports: [DatabaseModule],
  providers: [UsersService],
  controllers: [UsersController],
  exports: [UsersService],
})
class UsersModule {}

Bootstrap

import { bootstrap } from '@jamx-framework/core';

const app = await bootstrap({
  root: process.cwd(),
  hooks: {
    afterStart: ({ baseUrl }) => console.log(`Server ready at ${baseUrl}`),
  },
});

app.stop(); // Graceful shutdown

Ejemplos

Registro y resolución con scopes

// Singleton (por defecto)
Container.registerClass(UserService);

// Transient (nueva instancia cada resolución)
Container.register(UserService, { scope: 'transient' });

// Scoped (una instancia por scope)
const scopeId = Container.beginScope();
const instance1 = Container.resolve(UserService, scopeId);
const instance2 = Container.resolve(UserService, scopeId);
expect(instance1).toBe(instance2);
Container.endScope(scopeId);

Uso de decoradores

// Clase inyectable con dependencias
@injectable()
class AuthService {
  constructor(@inject(PasswordHasher) private hasher: PasswordHasher) {}
}

// Parámetro inyectable
class LoginController {
  constructor(@inject(AuthService) private auth: AuthService) {}

  async login(email: string, password: string) {
    const hashed = await this.auth.hasher.verify(password, storedHash);
    if (!hashed) throw new UnauthorizedException('Invalid credentials');
    return { token: await this.auth.createToken({ email }) };
  }
}

Bootstrap con hooks

import { bootstrap } from '@jamx-framework/core';

await bootstrap({
  silent: false,
  hooks: {
    beforeConfig: () => console.log('Cargando configuración...'),
    afterConfig: (config) => console.log(`Modo: ${config.env}`),
    afterStart: ({ baseUrl }) => console.log(`🚀 Servidor escuchando en ${baseUrl}`),
    onShutdown: async () => {
      await someCleanupTask();
      console.log('🔌 Conexiones cerradas');
    },
  },
});

Flujo interno

  1. Inicialización del Container: Se crea una instancia global de Container.
  2. Registro de dependencias: Los módulos y decoradores registran providers (ClassProvider, ValueProvider, FactoryProvider).
  3. Resolución: Cuando se llama a Container.resolve(), se crea la instancia resolviendo dependencias recursivamente.
  4. Manejo de scopes: Los scopes permiten instancias aisladas para requests HTTP o transacciones.
  5. Detección de ciclos: Se lanza CircularDependencyError si se detecta un ciclo de dependencias.
  6. Bootstrap: La función bootstrap() carga configuración, inicializa módulos y arranca servidores mediante hooks.
  7. Plugins: PluginRegistry gestiona plugins con dependencias y permite ordenar su ejecución mediante topological sort.
  8. Documentación: DocGenerator puede generar documentación a partir de endpoints registrados.

Plugin Development

Para crear un plugin personalizado:

  1. Implementa una clase que exponga meta (nombre, dependencias) y métodos setup(ctx) y teardown?(ctx).
  2. Regístralo en PluginRegistry.
  3. Asegúrate de que setup() reciba el contexto adecuado (por ejemplo, Container).

Ejemplo mínimo:

import type { Plugin, PluginContext } from '@jamx-framework/core';

export class LoggingPlugin implements Plugin<PluginContext> {
  meta = { name: 'logging' };

  async setup(ctx: PluginContext) {
    console.log('[Plugin] Logging initialized');
  }
}

// Registro
Container.registerPlugin(LoggingPlugin);

Testing

El proyecto incluye tests unitarios en packages/core/tests/unit/. Para ejecutarlos:

pnpm test
# o
npm run test

Los tests cubren:

  • Registro y resolución de dependencias
  • Manejo de scopes y ciclos
  • Decoradores @injectable() y @inject()
  • Funcionalidad de bootstrap() con hooks
  • Integración con PluginRegistry

Compatibility

  • Compatible con Node.js 18+ y TypeScript 5.x
  • Funciona en Windows, macOS y Linux
  • No tiene dependencias de runtime; solo devDependencies para testing
  • Diseñado para ser usado como base de cualquier aplicación JAMX

Configuration Options

El núcleo no requiere configuración explícita. Sin embargo, puedes personalizar el comportamiento mediante:

  1. Hooks en bootstrap: Personaliza el ciclo de vida de la aplicación.
  2. Middlewares: Añade lógica antes/durante/después de los handlers.
  3. Transformación de tokens: Modifica cómo se identifican las dependencias.

CLI Integration

Este paquete se integra automáticamente con el CLI de JAMX:

  • jamx build: Compila el código fuente a dist/.
  • jamx dev: Inicia un entorno de desarrollo que simula el bootstrap.
  • jamx check: Verifica que el proyecto tenga la configuración mínima (jamx.config.ts).

License

MIT © Stiven-21

This core package provides the foundational building blocks for building modular, type-safe applications with JAMX Framework, enabling developers to manage dependencies cleanly, extend functionality through plugins, and bootstrap applications with a consistent lifecycle.