JSPM

@jamx-framework/plugins

2.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 7
  • Score
    100M100P100Q65669F
  • License MIT

JAMX Framework — Plugin system and marketplace

Package Exports

  • @jamx-framework/plugins

Readme

@jamx-framework/plugins

Descripción

Sistema de plugins para JAMX Framework. Proporciona una arquitectura extensible que permite añadir funcionalidades al framework mediante plugins, con registro automático, gestión de dependencias entre plugins, y un marketplace para descubrir e instalar plugins de la comunidad. Los plugins pueden extender el core, añadir adaptadores, comandos CLI, o integraciones con servicios externos.

Cómo funciona

El sistema de plugins implementa un registro centralizado con dependencias y ciclo de vida:

  1. Plugin Registry: Registra plugins disponibles y gestiona su orden de carga
  2. Plugin Loader: Carga plugins desde archivos o paquetes npm
  3. Marketplace: Catálogo de plugins públicos/privados para descubrimiento
  4. Built-in Plugins: Plugins incluidos por defecto en JAMX

Componentes principales

  • src/plugin-registry.ts: PluginRegistry que gestiona registro y orden de plugins
  • src/plugin-loader.ts: PluginLoader que carga plugins desde disco o npm
  • src/marketplace.ts: Marketplace para buscar y descargar plugins
  • src/built-in-plugins.ts: Lista de plugins incluidos por defecto
  • src/types.ts: Tipos (Plugin, PluginMeta, PluginContext)
  • src/index.ts: Punto de exportación

Uso básico

import { PluginRegistry, Plugin } from '@jamx-framework/plugins';

// Crear registry
const registry = new PluginRegistry();

// Definir un plugin
class MyPlugin implements Plugin {
  meta = {
    name: 'my-plugin',
    version: '1.0.0',
    dependencies: ['@jamx-framework/core'],
  };

  async setup(ctx) {
    console.log('Plugin my-plugin inicializado');
    // Registrar servicios, comandos, etc.
  }

  async teardown(ctx) {
    console.log('Plugin my-plugin limpiando');
  }
}

// Registrar y ejecutar
registry.register(new MyPlugin());
await registry.setupAll(ctx);

Ejemplos

Plugin que añade un comando CLI

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

class MyCliPlugin implements Plugin {
  meta = {
    name: 'my-cli-plugin',
    version: '1.0.0',
    dependencies: ['@jamx-framework/cli'],
  };

  async setup(ctx: PluginContext) {
    // Registrar comando en CLI
    ctx.cli.registerCommand({
      name: 'my-command',
      description: 'Mi comando personalizado',
      action: async (options) => {
        console.log('Ejecutando mi comando');
      },
    });
  }
}

Plugin con dependencias

class AnalyticsPlugin implements Plugin {
  meta = {
    name: 'analytics',
    version: '1.0.0',
    dependencies: [
      '@jamx-framework/core',
      '@jamx-framework/events',
      '@jamx-framework/metrics',
    ],
  };

  async setup(ctx) {
    // Usar servicios de otras dependencias
    const events = ctx.container.resolve('eventBus');
    const metrics = ctx.container.resolve('metrics');
    
    events.on('user.created', (data) => {
      metrics.counter('users_created_total').increment();
    });
  }
}

Plugin que extiende el contenedor

class DatabasePlugin implements Plugin {
  meta = {
    name: 'database-extension',
    version: '1.0.0',
    dependencies: ['@jamx-framework/db'],
  };

  async setup(ctx) {
    const { Container } = await import('@jamx-framework/core');
    
    // Registrar servicios adicionales
    Container.registerSingleton('userRepository', () => {
      return new UserRepository(ctx.db);
    });
  }
}

Marketplace: instalar plugin

# Buscar plugins
jamx plugins:search analytics

# Instalar plugin
jamx plugins:install @jamx-plugin/analytics

# Listar plugins instalados
jamx plugins:list

# Actualizar plugins
jamx plugins:update

# Desinstalar plugin
jamx plugins:uninstall @jamx-plugin/analytics

Configuración de plugins en jamx.config.ts

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

export default defineConfig({
  plugins: [
    '@jamx-plugin/analytics',
    '@jamx-plugin/monitoring',
    // Plugins locales
    './plugins/my-local-plugin.js',
  ],
  
  pluginOptions: {
    analytics: {
      apiKey: process.env.ANALYTICS_KEY,
      endpoint: 'https://analytics.example.com',
    },
    monitoring: {
      enabled: true,
      sampleRate: 0.1,
    },
  },
});

Flujo interno

  1. Discovery: El PluginLoader busca plugins en node_modules, directorio local, o registry npm
  2. Loading: Carga el módulo del plugin (ESM o CommonJS)
  3. Validation: Verifica que el plugin exporte una clase que implemente Plugin interface
  4. Registration: Añade el plugin a PluginRegistry
  5. Dependency resolution: Ordena plugins según dependencias (topological sort)
  6. Setup: Ejecuta setup() de cada plugin en orden, inyectando PluginContext
  7. Teardown: Al cerrar la app, ejecuta teardown() en orden inverso

API Reference (Resumen)

Plugin (interface)

interface Plugin<TContext extends PluginContext = PluginContext> {
  meta: PluginMeta;
  setup(ctx: TContext): Promise<void> | void;
  teardown?(ctx: TContext): Promise<void> | void;
}

PluginMeta

  • name: string
  • version: string
  • description?: string
  • dependencies?: string[] (otros plugins o paquetes)
  • peerDependencies?: string[]
  • optionalDependencies?: string[]

PluginContext

  • container: Container
  • config: Record<string, any>
  • logger: Logger
  • cli?: CLI
  • server?: Server
  • db?: Database
  • etc. (todos los servicios disponibles)

PluginRegistry

  • register(plugin: Plugin): this
  • registerAll(plugins: Plugin[]): this
  • setupAll(ctx: PluginContext): Promise<void>
  • teardownAll(ctx: PluginContext): Promise<void>
  • has(name: string): boolean
  • list(): Plugin[]
  • resolveOrder(): Plugin[] (topological sort)

PluginLoader

  • loadFromPath(path: string): Promise<Plugin>
  • loadFromPackage(name: string): Promise<Plugin>
  • loadAllFromDir(dir: string): Promise<Plugin[]>

Marketplace

  • search(query: string): Promise<PluginInfo[]>
  • install(name: string, version?: string): Promise<void>
  • uninstall(name: string): Promise<void>
  • listInstalled(): Promise<InstalledPlugin[]>
  • update(name?: string): Promise<void>

Performance Considerations

  • Lazy loading: Los plugins se cargan solo cuando se necesitan
  • Dependency caching: Las dependencias se resuelven una vez y se cachean
  • Parallel setup: Los plugins sin dependencias cruzadas pueden inicializarse en paralelo
  • Tree-shaking: Solo se incluyen plugins usados en el build final

Configuration Options

// jamx.config.ts
export default defineConfig({
  plugins: [
    // Plugins desde npm
    '@jamx-plugin/analytics@^2.0.0',
    '@jamx-plugin/cache@latest',
    
    // Plugins locales (desarrollo)
    './plugins/local-plugin.js',
  ],
  
  // Opciones específicas por plugin
  pluginOptions: {
    analytics: {
      apiKey: 'xxx',
      endpoint: 'https://api.example.com',
      sampleRate: 0.1,
    },
    cache: {
      driver: 'redis',
      ttl: 3600,
    },
  },
  
  // Habilitar/deshabilitar plugins
  disabledPlugins: ['@jamx-plugin/experimental'],
});

Testing

Tests en packages/plugins/tests/unit/:

pnpm test

Cubre:

  • Registro de plugins
  • Resolución de dependencias
  • Orden de setup/teardown
  • Carga desde archivos
  • Marketplace (mock)

Compatibility

  • Compatible con Node.js 18+
  • Funciona con ESM y CommonJS
  • Plugins pueden ser paquetes npm o archivos locales
  • Soporta versionado semántico

CLI Integration

  • jamx plugins:search <query>: Busca plugins en marketplace
  • jamx plugins:install <name>: Instala plugin desde npm
  • jamx plugins:list: Lista plugins instalados
  • jamx plugins:uninstall <name>: Desinstala plugin
  • jamx plugins:update [name]: Actualiza plugins
  • jamx plugins:create <name>: Scaffold de plugin nuevo

Best Practices

  1. Mantener plugins pequeños: Un plugin = una funcionalidad
  2. Declarar dependencias: Especificar dependencies en meta
  3. Implementar teardown: Limpiar recursos al desinstalar
  4. Usar context: Acceder a servicios a través de ctx.container.resolve()
  5. Versionado semántico: Seguir semver para compatibilidad
  6. Documentar: Incluir README en cada plugin
  7. Testing: Escribir tests para el plugin

Publishing Plugins

Para publicar un plugin en el marketplace:

  1. Crear paquete npm con @jamx-plugin/ prefix
  2. Exportar clase que implemente Plugin
  3. Incluir jamx.plugin.json con metadatos
  4. Publicar en npm: npm publish --access public
  5. Enviar PR al marketplace para listado

Ejemplo de jamx.plugin.json:

{
  "name": "@jamx-plugin/analytics",
  "version": "1.0.0",
  "description": "Analytics plugin for JAMX",
  "author": "Your Name",
  "license": "MIT",
  "keywords": ["jamx", "plugin", "analytics"],
  "jamx": {
    "type": "plugin",
    "entry": "./dist/index.js",
    "dependencies": ["@jamx-framework/core"],
  }
}

This plugin system provides a powerful extension mechanism for JAMX Framework, enabling developers to create, share, and consume plugins that enhance the framework's capabilities in a modular, dependency-aware manner.