Un módulo puede publicar funciones que otros utilicen. Por ejemplo, el editor de controles admite botones e iconos aportados por otro módulo.
Declarar una integración
- El proveedor declara sus ganchos en
provides. - El consumidor declara proveedor, gancho y versión en
consumes. - Ambos declaran el permiso
modules.hooks.
Marca optional:true si el consumidor debe funcionar aunque falte el proveedor.
Añadir un botón al editor de controles
await host.hooks.contribute(
'nelkano.control-editor', 'system-buttons', 'my-button',
{ actionId: 'my-action', label: 'Mi botón', icon: 'assets/button.png' }
);
Añade assets/button.png a files. Cuando el usuario pulse el botón, tu módulo recibe onHook con operation:'my-action'. El editor entrega el contexto de partida en request.value.context; úsalo en las operaciones de emulación.
La app incluye el proveedor nelkano.control-editor. La plantilla Editor de controles de Studio utiliza example.control-editor: para probar con ella, usa ese ID tanto en consumes.provider como en hooks.contribute y carga también la carpeta del proveedor en Studio.
Con target:'sys-pause' puedes reutilizar un control existente y conservar su posición. Sin target, se añade un control independiente.
Consultar y llamar a un gancho
hooks.status: comprobar disponibilidad.hooks.list: obtener aportaciones.hooks.invoke: llamar al proveedor.invokeContributor: responder al consumidor desde el proveedor.
Entradas y salidas deben cumplir el esquema del gancho. Al desactivar o retirar un módulo desaparecen sus botones e iconos. El editor conserva las elecciones para cuando se reactive.
Publicar un servicio
Declara modules.services y registra name, version y methods. Cada método define input/output con los mismos tipos de esquema que los ganchos.
await host.services.register({
name: "example.counter", version: "1.0.0",
methods: { add: { input: {type: "integer"}, output: {type: "integer"} } }
});
// Otro módulo, con modules.services:
const next = await host.services.call("example.counter", "add", 4);
// El proveedor implementa onService(request) y devuelve el resultado.
Implementa onService: recibe service, method, value, caller y provider, con la identidad real del módulo y autor. La base usa author:builtin. El servicio se ejecuta dentro del entorno aislado del proveedor.
list(name)encuentra proveedores.unregister(name)retira únicamente los tuyos.calladmite proveedor, autor y versión mínima compatible dentro de la misma versión mayor.
Un mismo nombre y versión mayor deben mantener métodos y esquemas. El servicio no comparte código ni datos privados. Se rechazan ciclos y llamadas a un entorno ocupado. Límites: 256 proveedores, 32 métodos, profundidad de esquema 8 y datos de hasta 96 KiB.
Elegir el proveedor de una llamada
Indica options.provider en services.call para elegir uno concreto. Sin proveedor explícito ni preferencia guardada, se utiliza la implementación integrada; si no existe, se puede elegir al único proveedor disponible. Si hay varios y ninguno integrado, debes elegir.
Cada llamada verifica permisos y compatibilidad del contrato.
Ofrecer otro comportamiento de emulación
La base publica nelkano.emulation versión 1.0.0, método execute, entrada {operation,args} y salida {value:resultado}. Consulta list("nelkano.emulation") para copiar el contrato exacto.
Abarca snapshot, pausa/reset, presentación, guardar/cargar, library.launch y library.setCover. Las API anteriores delegan en él conservando sus permisos. Otro proveedor puede cambiar el comportamiento y delegar a la base con provider:"nelkano.base",author:"builtin".
Consumidor y proveedor necesitan el permiso original de cada operación. Este servicio afecta a las operaciones solicitadas por módulos; no sustituye las llamadas internas de la app ni los motores nativos.
Enviar eventos entre módulos
Con modules.events:
- Publica un tema con
define(topic,schema). Su nombre debe empezar por el ID de tu módulo y un punto. - Otro módulo se suscribe con
subscribe(topic), incluso antes de que exista el publicador. - El publicador envía con
emit(topic,value). Sólo él puede emitir. - El suscriptor recibe
onEventcon{type:"module-event",topic,value,sender:{moduleId,author}}.unsubscribe(topic)cancela la suscripción.
Son eventos locales; no se envían a servidores. Límites: 256 temas, 64 suscripciones y 64 eventos pendientes por módulo. Si se llena una cola, se rechaza todo el envío sin entregas parciales.
Se entregan hasta ocho eventos por ronda, aproximadamente cada 50 ms en primer plano, sin garantía de persistencia ni de tiempo exacto. Desactivar limpia servicios, temas, suscripciones y colas. Los ganchos siguen disponibles y Studio reproduce estos contratos.
Transformar una llamada antes o después de ejecutarla
Registra services.intercept({id,name,method,phase,order}) con fase before o after. onService recibe phase y hookId; devuelve un valor compatible con el esquema del método. Retira la transformación con removeInterceptor(id).
Admite 32 por módulo y 128 globales. Las llamadas propias no vuelven a entrar en su interceptor. Un error posterior a la operación no deshace sus efectos.