WU / DOCSUNIVERSAL MICROFRONTENDS
ES

Eventos, RPC y contratos

Tres mecanismos concretos de comunicación: notificar hechos, pedir respuestas y consumir servicios versionados.

Elige por el tipo de interacción

Necesidad API Resultado
Notificar un hecho sin respuesta emit / on Evento con identidad y datos
Pedir una respuesta a un proveedor request / handle Promesa con valor o error
Invocar métodos de un servicio local provide / consume Proxy de un contrato versionado

Los tres mecanismos viven en el proceso JavaScript del navegador. RPC en este contexto no implica HTTP ni transporte entre servidores. Una implementación puede hacer fetch por dentro, pero ese efecto y su autorización pertenecen a la implementación.

Los fragmentos que usan wu presuponen import { wu } from 'wu-framework' en el módulo cliente del shell y su inicialización con await wu.init(...). Los fragmentos con appWu usan el context.wu entregado a una app en mount(container, context). Para copiar un ejemplo completo, sigue Una suma entre aplicaciones: cliente, proveedor, manifests, grants y página Astro, con una respuesta observable y un caso de error recuperable.

Eventos y envelope

// Código del shell, con autoridad host.
const stop = wu.on('catalog:*', (event) => {
  console.log(event.name, event.data, event.appName, event.verified);
});

const accepted = wu.emit('catalog:selected', { productId: 'p-42' });
if (!accepted) console.info('El bus rechazó el evento');
stop();

El callback recibe un objeto con name, data, timestamp, appName, meta y verified. Los datos se separan y congelan al cruzar la frontera del bus. once elimina su suscripción después de la primera entrega; off retira una suscripción concreta.

Desde una app usa context.wu.on y context.wu.emit. La facade adjunta su identidad y verifica los grants. En modo estricto, emitir sin identidad válida, sin capacidad o hacia un namespace reservado devuelve false. Las suscripciones y el RPC denegados pueden lanzar errores: comprueba el booleano de emit y maneja las excepciones de las APIs que las producen.

El bus guarda hasta 100 eventos por defecto. eventBus.replay(pattern, callback) vuelve a entregar entradas existentes al callback suministrado; no vuelve a ejecutar el sistema ni garantiza recuperar efectos externos. history: false permite excluir una emisión del historial.

RPC con timeout y versión

const release = wu.eventBus.handle('catalog:lookup', ({ productId }) => {
  return { productId, title: 'Producto de demostración' };
}, { version: '1.0.0', allow: ['search'] });

// Dentro del lifecycle de la app search, con rpc.call:catalog:lookup:
async function lookup(appWu, productId, signal) {
  return appWu.request('catalog:lookup', { productId }, {
    version: '^1.0.0',
    timeout: 2500,
    signal,
  });
}

// Cuando el proveedor del shell ya no deba atender:
release();

Una app proveedora necesita rpc.provide y una consumidora rpc.call sobre el canal. Además, allow filtra identidades de llamadas. Para un proveedor app scoped en modo estricto, el allow por defecto permite a esa misma app; para comunicación entre apps declara los consumidores explícitos.

wu.handle(channel, handler, options) conserva version, allow y replace. Dentro del lifecycle, context.wu.handle añade además la identidad y los grants de la app; utiliza esa facade para handlers de una microapp.

El timeout por defecto de request es 0, sin límite temporal. Usa uno finito para interacciones de UI. El handler recibe un segundo argumento con datos de correlación e identidad y un signal. Debe cooperar con ese signal para cancelar trabajo propio; rechazar la espera no revierte una operación ya realizada.

Un canal tiene un proveedor activo. Reemplazar el mismo proveedor requiere { replace: true } bajo las condiciones estrictas; otra identidad no puede apropiarse de un canal ya poseído. Liberación, reemplazo y revocación del proveedor abortan solicitudes asociadas. El bus emite trazas <canal>:request, <canal>:response y <canal>:error con correlación.

Contratos de métodos locales

const handle = wu.provide('formatters', {
  price(value) {
    return new Intl.NumberFormat('es-MX', {
      style: 'currency', currency: 'MXN',
    }).format(value);
  },
}, {
  version: '1.0.0',
  shape: { price: 'function' },
});

const formatters = wu.consume('formatters', '^1.0.0');
console.log(formatters.price(120));
handle.revoke();

consume entrega un proxy vivo. Sin { wait: true }, crear el proxy no exige que exista el proveedor: el primer acceso a un miembro valida existencia y versión. Con { wait: true, timeout: 2500 }, espera hasta encontrar un proveedor compatible.

La versión por defecto de provide es 0.0.0, distinta de handle RPC, cuyo default es 1.0.0. shape verifica presencia o typeof de miembros; no sustituye un schema completo de argumentos/resultados.

Una facade app exige rpc.provide/rpc.call también para contratos y asocia automáticamente el proveedor a la app. Los proxies consumidos no son promesas; un método llamado literalmente then no se alcanza por esa vía. Contratos no implementa la misma allowlist ni la misma separación de payloads que el RPC del bus; elige el contrato atendiendo a ese límite.

Errores que conviene manejar

Código RPC Causa
WU_RPC_NO_HANDLER No hay proveedor del canal
WU_RPC_VERSION_MISMATCH La versión no satisface el rango
WU_RPC_CALLER_DENIED El consumidor no está en allow
WU_RPC_CALL_DENIED / WU_RPC_PROVIDE_DENIED Falta grant efectivo
WU_RPC_CHANNEL_OWNED Otro dueño ya registró el canal
WU_RPC_REPLACE_REQUIRED Falta intención explícita de reemplazo
WU_RPC_PROVIDER_RELEASED / WU_RPC_PROVIDER_REPLACED El proveedor dejó de ser el mismo durante la petición

Referencia de implementación

Eventos: src/core/wu-event-bus.js; RPC: src/core/wu-event-bus.js y src/core/wu-event-bus.js; atajo handle del singleton: src/index.js; replay: src/core/wu-event-bus.js; contratos: src/core/wu-contracts.js y src/core/wu-contracts.js; facade: src/core/wu-core.js. Pruebas: tests/unit/event-bus.test.js, tests/unit/contracts.test.js, tests/unit/capability-security-v3.test.js, tests/unit/scoped-events-teardown.test.js.

El primer proveedor conserva la propiedad del nombre de un contrato. Otra app, o el host sobre un contrato de app, recibe WU_CAPABILITY_OWNED hasta que el propietario revoque el contrato o se desmonte. El mismo propietario puede reemplazar su implementación. Cuando hay shape, los puertos remotos solo exponen los métodos declarados por ella.

WU SE CONSTRUYE CONTIGO

¿Encontraste un bug? ¿Tienes una idea?

Tu experiencia mejora WU. Cuéntanos qué falla o ayuda a sostener su desarrollo.