@jamx-framework/plugins
v2.0.0
Published
JAMX Framework — Plugin system and marketplace
Maintainers
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:
- Plugin Registry: Registra plugins disponibles y gestiona su orden de carga
- Plugin Loader: Carga plugins desde archivos o paquetes npm
- Marketplace: Catálogo de plugins públicos/privados para descubrimiento
- Built-in Plugins: Plugins incluidos por defecto en JAMX
Componentes principales
- src/plugin-registry.ts:
PluginRegistryque gestiona registro y orden de plugins - src/plugin-loader.ts:
PluginLoaderque carga plugins desde disco o npm - src/marketplace.ts:
Marketplacepara 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/analyticsConfiguració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
- Discovery: El
PluginLoaderbusca plugins ennode_modules, directorio local, o registry npm - Loading: Carga el módulo del plugin (ESM o CommonJS)
- Validation: Verifica que el plugin exporte una clase que implemente
Plugininterface - Registration: Añade el plugin a
PluginRegistry - Dependency resolution: Ordena plugins según dependencias (topological sort)
- Setup: Ejecuta
setup()de cada plugin en orden, inyectandoPluginContext - 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: stringversion: stringdescription?: stringdependencies?: string[](otros plugins o paquetes)peerDependencies?: string[]optionalDependencies?: string[]
PluginContext
container: Containerconfig: Record<string, any>logger: Loggercli?: CLIserver?: Serverdb?: Database- etc. (todos los servicios disponibles)
PluginRegistry
register(plugin: Plugin): thisregisterAll(plugins: Plugin[]): thissetupAll(ctx: PluginContext): Promise<void>teardownAll(ctx: PluginContext): Promise<void>has(name: string): booleanlist(): 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 testCubre:
- 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 marketplacejamx plugins:install <name>: Instala plugin desde npmjamx plugins:list: Lista plugins instaladosjamx plugins:uninstall <name>: Desinstala pluginjamx plugins:update [name]: Actualiza pluginsjamx plugins:create <name>: Scaffold de plugin nuevo
Best Practices
- Mantener plugins pequeños: Un plugin = una funcionalidad
- Declarar dependencias: Especificar
dependenciesenmeta - Implementar teardown: Limpiar recursos al desinstalar
- Usar context: Acceder a servicios a través de
ctx.container.resolve() - Versionado semántico: Seguir semver para compatibilidad
- Documentar: Incluir README en cada plugin
- Testing: Escribir tests para el plugin
Publishing Plugins
Para publicar un plugin en el marketplace:
- Crear paquete npm con
@jamx-plugin/prefix - Exportar clase que implemente
Plugin - Incluir
jamx.plugin.jsoncon metadatos - Publicar en npm:
npm publish --access public - 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.
