@jumentix/message-mediator
Pacote de workspace para contratos do Message Mediator Jumentix e seu adaptador in-memory de referência.
Escopo extraído atual:
- contratos principais (
IMessage,IMessageResponse, metadados) - barramento de eventos e interfaces de mediador
- adaptador in-memory;
- adaptador RabbitMQ;
- adaptador BullMQ;
- helper
compileMessageMediatororientado pelo ambiente.
Responsabilidade no escopo
- Camada: messaging / adaptador de aplicação
- Responsável por: mediação em processo ou via broker
- Usado com: use-cases de backend
- Não responsável por: rotas OpenAPI ou persistência de banco
Experimente no navegador
Mediator in-memory:
Mediator em memória
Troque mensagens entre os domínios Category e Task e componha um read model via request/response do mediator.
### Mediator em memória
```ts
const domainMessages = [];
const events = [];
const mediator = api.createInMemory();
const categories = new Map([
['work', { id: 'work', name: 'Work', color: '#2563eb' }],
['home', { id: 'home', name: 'Home', color: '#16a34a' }]
]);
const tasks = [];
await mediator.subscribe('tasks.created', async (event) => {
events.push({
title: event.payload.title,
categoryId: event.payload.categoryId
});
});
mediator.registerHandler('categories.get.v1', async (message) => {
domainMessages.push({
from: message.metadata.sourceDomain,
to: 'Categories',
contract: 'categories.get.v1',
categoryId: message.payload.id
});
return {
ok: true,
result: categories.get(message.payload.id) ?? null
};
});
mediator.registerHandler('tasks.create.v1', async (message) => {
const task = {
id: message.payload.id,
title: message.payload.title,
categoryId: message.payload.categoryId,
completed: false
};
tasks.push(task);
await mediator.publish({ name: 'tasks.created', payload: task });
return { ok: true, result: task };
});
mediator.registerHandler('tasks.board.v1', async () => {
const cards = await Promise.all(tasks.map(async (task) => {
const category = await mediator.request({
contract: 'categories.get.v1',
payload: { id: task.categoryId },
metadata: {
sourceDomain: 'Tasks',
reason: 'compose task board read model'
}
});
return {
id: task.id,
title: task.title,
categoryName: category.result?.name ?? 'Uncategorized',
categoryColor: category.result?.color ?? '#64748b'
};
}));
return {
ok: true,
result: {
readModel: 'TaskBoard',
composedFrom: ['Tasks', 'Categories'],
cards
}
};
});
const response = await mediator.request({
contract: 'tasks.create.v1',
payload: {
id: 'task-1',
title: 'Wire mediator events',
categoryId: 'work'
},
metadata: { source: 'browser-playground' }
});
const board = await mediator.request({
contract: 'tasks.board.v1',
payload: {},
metadata: { source: 'task-board-page' }
});
return {
createdTask: response.result,
board: board.result,
domainMessages,
events
};
```const domainMessages = [];
const events = [];
const mediator = api.createInMemory();
const categories = new Map([
['work', { id: 'work', name: 'Work', color: '#2563eb' }],
['home', { id: 'home', name: 'Home', color: '#16a34a' }]
]);
const tasks = [];
await mediator.subscribe('tasks.created', async (event) => {
events.push({
title: event.payload.title,
categoryId: event.payload.categoryId
});
});
mediator.registerHandler('categories.get.v1', async (message) => {
domainMessages.push({
from: message.metadata.sourceDomain,
to: 'Categories',
contract: 'categories.get.v1',
categoryId: message.payload.id
});
return {
ok: true,
result: categories.get(message.payload.id) ?? null
};
});
mediator.registerHandler('tasks.create.v1', async (message) => {
const task = {
id: message.payload.id,
title: message.payload.title,
categoryId: message.payload.categoryId,
completed: false
};
tasks.push(task);
await mediator.publish({ name: 'tasks.created', payload: task });
return { ok: true, result: task };
});
mediator.registerHandler('tasks.board.v1', async () => {
const cards = await Promise.all(tasks.map(async (task) => {
const category = await mediator.request({
contract: 'categories.get.v1',
payload: { id: task.categoryId },
metadata: {
sourceDomain: 'Tasks',
reason: 'compose task board read model'
}
});
return {
id: task.id,
title: task.title,
categoryName: category.result?.name ?? 'Uncategorized',
categoryColor: category.result?.color ?? '#64748b'
};
}));
return {
ok: true,
result: {
readModel: 'TaskBoard',
composedFrom: ['Tasks', 'Categories'],
cards
}
};
});
const response = await mediator.request({
contract: 'tasks.create.v1',
payload: {
id: 'task-1',
title: 'Wire mediator events',
categoryId: 'work'
},
metadata: { source: 'browser-playground' }
});
const board = await mediator.request({
contract: 'tasks.board.v1',
payload: {},
metadata: { source: 'task-board-page' }
});
return {
createdTask: response.result,
board: board.result,
domainMessages,
events
};Documentação completa
Veja o guia de uso.