mediator
kz is a collection of easy-to-use utility and feature libraries for creating anything you want with the Deno runtime.
@kz/mediator
The @kz/patterns/mediator
module provides types and features for implementing the mediator pattern.
Overview |
API Docs
## Examples
```ts
import { AbstractDisposable } from '@kz/dispose';
import { TAbstractObserver } from '@kz/observe';
import { type PubSubTopicMessage, TAbstractSubscriber } from '@kz/pubsub';
import {
type ParticipantTopicMessage,
TAbstractParticipant,
TBaseMediator,
} from './mod.ts';
interface IUserResponse {
name: string;
birthYear: string;
}
type MediatorTopics = {
'get_users': undefined;
'get_user': number;
'user_response': IUserResponse;
'users_response': IUserResponse[];
};
class SwapiClient extends AbstractDisposable {
protected cache = new Map();
constructor(protected baseUrl: string = 'https://swapi.dev/api') {
super();
}
public dispose(): void {
this.cache.clear();
}
protected async request(slug: string, id?: number): Promise {
const { cache, baseUrl } = this;
const uri = id ? `${baseUrl}/${slug}/${id}` : `${baseUrl}/${slug}`;
const cached = cache.get(uri);
if (cached) return cached;
const response = await fetch(uri);
const data = await response.text();
cache.set(uri, data);
return data;
}
public async getPeople(id?: number): Promise {
return await this.request('people', id);
}
}
const client = new SwapiClient();
class DataBus extends TBaseMediator {
}
type DataBusRequest = Extract;
class UserDataHandler
extends TAbstractParticipant {
public next(
value: ParticipantTopicMessage,
): void {
const [topic, message] = value;
if (topic === 'get_users') {
client.getPeople().then((data) => {
const users = JSON.parse(data) as { results: any[] };
const userData = users.results.map((user) => {
return { name: user.name, birthYear: user.birth_year };
}) as IUserResponse[];
this.publish(['users_response', userData]);
});
}
if (topic === 'get_user') {
client.getPeople(message).then((data) => {
const user = JSON.parse(data);
const userData = {
name: user.name,
birthYear: user.birth_year,
} as IUserResponse;
this.publish(['user_response', userData]);
});
}
}
public error(error: Error): void {
console.error(error);
}
}
// Will receive all messages from the mediator and be able to send requests back.
class UserParticipant extends TAbstractParticipant {
public next(value: ParticipantTopicMessage): void {
const [topic] = value;
console.log(`Participant(${topic}): Received a user update`);
}
public error(error: Error): void {
console.error(error);
}
}
// Yes! You can use pubsub subscriber to subscribe to a mediator.
// Will receive updated user information, but not the request to do so.
// Is unable to send requests back.
class UserSubscriber extends TAbstractSubscriber<
MediatorTopics,
'user_response' | 'users_response'
> {
public next(
value: ParticipantTopicMessage<
MediatorTopics,
'user_response' | 'users_response'
>,
): void {
const [topic, message] = value;
if (topic === 'user_response') {
console.log(
`UserSub(${topic}): Updating user to ${
(message as IUserResponse).name
}`,
);
} else {
console.log(
`UserSub(${topic}): Updating users ${
(message as IUserResponse[]).length
}`,
);
}
}
public error(error: Error): void {
console.error(error);
}
}
// Yes! You can use regular observers to subscribe to a mediator.
// Because they cannot specify a topic, they will receive all messages from the mediator.
class UserObserver
extends TAbstractObserver> {
public next(value: ParticipantTopicMessage): void {
const [topic] = value;
console.log(`Observer(${topic}): Received a user update`);
}
public error(error: Error): void {
console.error(error);
}
}
const bus = new DataBus();
const handler = new UserDataHandler(['get_users', 'get_user']);
const participant = new UserParticipant(['get_users', 'get_user']);
const subscriber = new UserSubscriber(['user_response', 'users_response']);
const observer = new UserObserver();
bus.subscribe(handler);
bus.subscribe(participant);
bus.subscribe(subscriber);
bus.subscribe(observer);
bus.publish(['get_users', undefined]); // go ahead and initialize data
bus.publish(['get_user', 1]); // get a specific user
participant.publish(['get_user', 2]); // get another specific user
```
## Contributing
Contributions are welcome! Take a look at our [contributing guidelines][contributing] to get started.
## License
The MIT License (MIT) 2020-2024 integereleven. Refer to [LICENSE][license] for details.
Built with ❤ by integereleven
[deno]: https://deno.dom "Deno homepage"
[jsr]: https://jsr.io "JSR homepage"
[branches]: https://github.com/kz-io/mediator/branches "@kz/mediator branches on GitHub"
[releases]: https://github.com/kz-io/mediator/releases "@kz/mediator releases on GitHub"
[contributing]: https://github.com/kz-io/mediator/blob/main/CONTRIBUTING.md "@kz/mediator contributing guidelines"
[license]: https://github.com/kz-io/mediator/blob/main/LICENSE "@kz/mediator license"