| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Angulator is a lightweight Angular mediator library, designed to simplify communication between different parts of your application using a request/response and notification/handler pattern.
Disclaimer: This is a project I made in my spare time for fun, but I hope someone gets some use out of it. Any comments, constructive criticism, ideas, or contributions are welcome.
This library uses decorators to automatically associate requests with handlers, which requires the reflect-metadata library. Please ensure you have it installed and imported in your application's polyfills.
npm install reflect-metadataThen, in your src/polyfills.ts (or src/main.ts):
import 'reflect-metadata';To install Angulator, run:
npm install @angulator/angulatorIn your AppModule or any feature module, use the provideMediator function to register your request and notification handlers:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { provideMediator } from '@angulator/angulator';
import { MyQueryHandler } from './my-query.handler';
import { MyCommandHandler } from './my-command.handler';
@NgModule({
declarations: [
// ...
],
imports: [BrowserModule],
providers: [provideMediator([MyQueryHandler, MyCommandHandler])],
bootstrap: [AppComponent],
})
export class AppModule {}// my-query.query.ts
import { IRequest } from '@angulator/angulator';
export class MyQuery implements IRequest<MyQueryResponse> {
constructor(public readonly id: number) {}
}
export class MyQueryResponse {
constructor(public readonly id: number, public readonly name: string) {}
}// my-query.handler.ts
import { IRequestHandler, RequestHandler } from '@angulator/angulator';
import { MyQuery, MyQueryResponse } from './my-query.query';
import { Observable, of } from 'rxjs';
@RequestHandler(MyQuery)
export class MyQueryHandler implements IRequestHandler<MyQuery, MyQueryResponse> {
handle(request: MyQuery): Observable<MyQueryResponse> {
return of(new MyQueryResponse(request.id, `Hello from query ${request.id}`));
}
}// my-command.command.ts
import { IRequest } from '@angulator/angulator';
export class MyCommand implements IRequest<void> {
constructor(public readonly id: number, public readonly message: string) {}
}// my-command.handler.ts
import { IRequestHandler, RequestHandler } from '@angulator/angulator';
import { MyCommand } from './my-command.command';
@RequestHandler(MyCommand)
export class MyCommandHandler implements IRequestHandler<MyCommand, void> {
handle(request: MyCommand): void {
console.log(`Command received: ${request.message} for ID: ${request.id}`);
}
}// user-created.notification.ts
import { INotification } from '@angulator/angulator';
export class UserCreatedNotification implements INotification {
constructor(public readonly userId: number, public readonly username: string) {}
}// user-created.handler.ts
import { INotificationHandler, NotificationHandler } from '@angulator/angulator';
import { UserCreatedNotification } from './user-created.notification';
@NotificationHandler(UserCreatedNotification)
export class UserCreatedNotificationHandler
implements INotificationHandler<UserCreatedNotification>
{
handle(notification: UserCreatedNotification): void {
console.log(`User created: ${notification.username} with ID: ${notification.userId}`);
}
}Inject the Mediator service into your components or services and use its send and publish methods:
import { Component, OnDestroy, inject } from '@angular/core';
import { Mediator } from '@angulator/angulator';
import { MyQuery, MyQueryResponse } from './my-query.query';
import { MyCommand } from './my-command.command';
import { UserCreatedNotification } from './user-created.notification';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
@Component({
selector: 'app-root',
template: `
<button (click)="sendQuery()">Send Query</button>
<button (click)="sendCommand()">Send Command</button>
<button (click)="publishNotification()">Publish Notification</button>
`,
})
export class AppComponent {
private readonly _mediator = inject(Mediator);
public readonly queryResponse = toSignal(
this.query$.pipe(
filter((id: number | null) => id !== null),
switchMap((id: number) => this._mediator.send(new MyQuery(id)))
)
);
private readonly _query = new BehaviorSubject<number | null>(null);
public readonly query$ = this._query.asObservable();
public sendQuery(id: number): void {
this._query.next(id);
}
public sendCommand(): void {
const command: MyCommand = new MyCommand(2, 'Perform an action');
this.mediator.send(command); // Commands typically return void
}
public publishNotification(): void {
const notification: UserCreatedNotification = new UserCreatedNotification(3, 'JohnDoe');
this.mediator.publish(notification);
}
}Implement IPipelineBehavior to create custom behaviors that can intercept requests.
// logging.behavior.ts
import { IPipelineBehavior, IRequest, RequestHandlerDelegate } from '@angulator/angulator';
import { Injectable } from '@angular/core';
@Injectable()
export class LoggingBehavior implements IPipelineBehavior {
public handle<TRequest extends IRequest<TResponse>, TResponse>(
request: TRequest,
next: RequestHandlerDelegate<TResponse>
): TResponse {
console.log(`[LoggingBehavior] Handling request: ${request.constructor.name}`);
const result: TResponse = next();
console.log(`[LoggingBehavior] Finished handling request: ${request.constructor.name}`);
return result;
}
}To register pipeline behaviors, provide them in your module:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { provideMediator, PIPELINE_BEHAVIORS } from '@angulator/angulator';
import { MyQueryHandler } from './my-query.handler';
import { LoggingBehavior } from './logging.behavior';
@NgModule({
// ...
providers: [
provideMediator([MyQueryHandler]),
{ provide: PIPELINE_BEHAVIORS, useClass: LoggingBehavior, multi: true },
],
// ...
})
export class AppModule {}Angulator provides schematics to quickly generate boilerplate code for your requests, commands, and their handlers.
To use the schematics, ensure you have @angular/cli installed globally or locally in your project.
ng generate @angulator/angulator:query <name> --project=angulatorThis will generate:
Example:
ng generate @angulator/angulator:query GetUser --project=angulatorng generate @angulator/angulator:command <name> --project=angulatorThis will generate:
Example:
ng generate @angulator/angulator:command CreateUser --project=angulatorThe following are the main exports from the angulator library that you will typically interact with:
For more information on using the Angular CLI, including detailed command references, visit the Angular CLI Overview and Command Reference page.
| Back | FazBrowse Home | New Git URL |