1.1.7 • Published 1 year ago

ts-request-mediator v1.1.7

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

NPM version:latest npm downloads npm bundle size (minified + gzip) Coverage Status License

Framework agnostic request mediator

Advantages

  • written on typescript
  • simple and lightweight
  • clean API
  • supports middlewares as decorators

Install

npm install ts-request-mediator reflect-metadata
yarn add ts-request-mediator reflect-metadata

tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Architecture design

Scopes

  • application
  • request
  • useCase
  • service

Request scope

  flowchart LR;
      requestHandler1-->requestHandler2-->id1{{targetHandler}}-->requestHandler3-->requestHandler4;

Example:

  flowchart LR;
      AuthorizeUser-->id1{{CreateTodo}}-->LogRequest;

Use case scope

  flowchart LR;
      useCaseHandler1-->useCaseHandler2-->id1{{targetHandler}}-->useCaseHandler3-->useCaseHandler4;

Example:

  flowchart LR;
      SetUserContext-->id1{{CreateTodo}}-->DoSmthAfter;

Service scope

  flowchart LR;
      serviceHandler1-->serviceHandler2-->id1{{targetHandler}}-->serviceHandler3-->serviceHandler4;

Usage

Describe a use case

import { IQueryHandler, request, context, transaction, useService, inject } from "ts-request-mediator";
import { by } from "ts-ioc-container";

@transaction
@request("before", [AuthorizeUser])
@request("after", [LogRequest])
@useCase("before", [SetUserContext])
class CreateTodo implements IQueryHandler<CreateTodoQuery, Todo> {
  constructor(
    @inject(by(ITodoRepositoryKey)) private todoRepository: ITodoRepository,
    @inject(context(IUserKey)) private user: IUser,
    @inject(useService(INotifyAllUsersKey, { transaction: true })) private notifyAllUsers: INotifyAllUsers
  ) {
  }

  @before
  validate(query: CreateTodoQuery): void {
    PermissionError.assert(this.user.isAdmin, "User has no permission to create a todo");
  }

  async handle(query: CreateTodoQuery): Promise<Todo> {
    const todo = await this.todoRepository.create(query);
    return todo;
  }

  @after
  async notify(query: CreateTodoQuery, todo: Todo): Promise<void> {
    await this.notifyAllUsers.handle(todo);
  }
}

const INotifyAllUsersKey = Symbol("INotifyAllUsers");
interface INotifyAllUsers extends IQueryHandler<Todo, void> {
}

class NotifyAllUsers implements INotifyAllUsers {
  constructor(
    @inject(by(INotificationServiceKey)) private notificationService: INotificationService
  ) {
  }

  async handle(todo: Todo): Promise<void> {
    const users = await this.userRepository.findAll();
    await this.notificationService.notify(users, `New todo created: ${todo.title}`);
  }
}

Wrap your dependency container into adapter

import { IDependencyContainer } from 'ts-ioc-container';

export class ContainerAdapter implements IDependencyContainer {
  constructor(private container: IContainer) {}

  createScope(tags: string[]): IDependencyContainer {
    return new ContainerAdapter(this.container.createScope(tags));
  }

  dispose(): void {
    this.container.dispose();
  }

  registerValue(key: string | symbol, value: unknown): void {
    this.container.register(fromValue(value).forKey(key).build());
  }

  resolve<T>(key: constructor<T> | symbol): T {
    return this.container.resolve(key);
  }
}

Create mediator

const mediator = new RequestMediator(new ContainerAdapter(container));

And finally invoke your use case

const todo = await mediator.send(CreateTodo, {title: 'Buy milk', description: '2% fat'});

Implement your transaction context and put into DI container

import { PrismaClient } from '@prisma/client';
import { forKey, Resolveable } from 'ts-ioc-container';
import { ITransactionContextKey, ITransactionContext } from 'ts-request-mediator';
import { perApplication } from '../../core/di';

@perApplication
@forKey(ITransactionContextKey)
export class PrismaTransactionContext implements ITransactionContext {
  constructor(public dbClient: PrismaClient = new PrismaClient()) {}

  execute<Response>(setContext: (context: ITransactionContext) => Promise<Response>): Promise<Response> {
    return this.dbClient.$transaction((transactionClient) =>
      setContext(new PrismaTransactionContext(transactionClient as PrismaClient)),
    );
  }
}

export const prismaClient = (c: Resolveable) =>
  l.resolve<PrismaTransactionContext>(ITransactionContextKey).dbClient;
1.1.7

1 year ago

1.1.6

1 year ago

1.1.5

1 year ago

1.1.4

1 year ago

1.0.62

1 year ago

1.0.61

1 year ago

1.0.60

1 year ago

1.0.63

1 year ago

1.1.1

1 year ago

1.1.0

1 year ago

1.1.3

1 year ago

1.1.2

1 year ago

1.0.59

1 year ago

1.0.55

1 year ago

1.0.54

1 year ago

1.0.53

1 year ago

1.0.58

1 year ago

1.0.57

1 year ago

1.0.56

1 year ago

1.0.49

1 year ago

1.0.50

1 year ago

1.0.52

1 year ago

1.0.48

1 year ago

1.0.47

1 year ago

1.0.46

1 year ago

1.0.45

1 year ago

1.0.44

1 year ago

1.0.43

1 year ago

1.0.42

1 year ago

1.0.39

1 year ago

1.0.38

1 year ago

1.0.40

1 year ago

1.0.41

1 year ago

1.0.37

1 year ago

1.0.36

1 year ago

1.0.35

1 year ago

1.0.34

1 year ago

1.0.29

1 year ago

1.0.28

1 year ago

1.0.33

1 year ago

1.0.32

1 year ago

1.0.31

1 year ago

1.0.30

1 year ago

1.0.27

1 year ago

1.0.26

1 year ago

1.0.25

1 year ago

1.0.24

1 year ago

1.0.22

1 year ago

1.0.20

1 year ago

1.0.23

1 year ago

1.0.19

1 year ago

1.0.18

1 year ago

1.0.17

1 year ago

1.0.16

1 year ago

1.0.15

1 year ago

1.0.9

1 year ago

1.0.11

1 year ago

1.0.10

1 year ago

1.0.14

1 year ago

1.0.13

1 year ago

1.0.12

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

0.10.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago

1.0.3

1 year ago

0.10.1

1 year ago

0.10.2

1 year ago

0.10.0

1 year ago

0.9.45

1 year ago

0.9.46

1 year ago

0.9.44

1 year ago

0.9.43

2 years ago

0.8.9

2 years ago

0.8.5

2 years ago

0.8.4

2 years ago

0.8.7

2 years ago

0.8.6

2 years ago

0.9.41

2 years ago

0.9.42

2 years ago

0.9.40

2 years ago

0.9.34

2 years ago

0.9.8

2 years ago

0.9.35

2 years ago

0.9.7

2 years ago

0.9.36

2 years ago

0.9.37

2 years ago

0.9.9

2 years ago

0.9.30

2 years ago

0.9.31

2 years ago

0.9.32

2 years ago

0.9.33

2 years ago

0.9.38

2 years ago

0.9.39

2 years ago

0.9.23

2 years ago

0.9.24

2 years ago

0.9.25

2 years ago

0.9.26

2 years ago

0.9.20

2 years ago

0.9.21

2 years ago

0.9.22

2 years ago

0.9.27

2 years ago

0.9.28

2 years ago

0.9.29

2 years ago

0.8.1

2 years ago

0.8.3

2 years ago

0.8.2

2 years ago

0.9.12

2 years ago

0.9.13

2 years ago

0.9.14

2 years ago

0.9.15

2 years ago

0.9.10

2 years ago

0.9.11

2 years ago

0.9.16

2 years ago

0.9.17

2 years ago

0.9.18

2 years ago

0.9.19

2 years ago

0.8.0

2 years ago

0.7.40

2 years ago

0.7.39

2 years ago

0.7.38

2 years ago

0.7.37

2 years ago

0.7.36

2 years ago

0.7.35

2 years ago

0.7.34

2 years ago

0.7.33

2 years ago

0.7.32

2 years ago

0.7.31

2 years ago

0.7.30

2 years ago

0.7.29

2 years ago

0.7.28

2 years ago

0.7.27

2 years ago

0.7.26

2 years ago

0.7.25

2 years ago

0.7.24

2 years ago

0.7.23

2 years ago

0.7.22

2 years ago

0.7.21

2 years ago

0.7.20

2 years ago

0.7.19

2 years ago

0.7.18

2 years ago

0.7.17

2 years ago

0.7.16

2 years ago

0.7.15

2 years ago

0.7.14

2 years ago

0.7.13

2 years ago

0.7.12

2 years ago

0.7.11

2 years ago

0.7.10

2 years ago

0.7.9

2 years ago

0.7.8

2 years ago

0.7.7

2 years ago

0.7.6

2 years ago

0.7.5

2 years ago

0.7.4

2 years ago

0.7.3

2 years ago

0.7.0

2 years ago

0.6.0

2 years ago

0.5.0

2 years ago

0.4.0

2 years ago

0.3.3

2 years ago

0.3.2

2 years ago

0.3.1

2 years ago

0.3.0

2 years ago

0.2.31

2 years ago

0.2.30

2 years ago

0.2.29

2 years ago

0.2.28

2 years ago

0.2.27

2 years ago

0.2.26

2 years ago

0.2.25

2 years ago

0.2.24

2 years ago

0.2.23

2 years ago

0.2.22

2 years ago

0.2.21

2 years ago

0.2.20

2 years ago

0.2.19

2 years ago

0.2.18

2 years ago

0.2.17

2 years ago

0.2.16

2 years ago

0.2.15

2 years ago

0.2.14

2 years ago

0.2.13

2 years ago

0.2.12

2 years ago

0.2.11

2 years ago

0.2.10

2 years ago

0.2.9

2 years ago

0.2.8

2 years ago

0.2.7

2 years ago

0.2.6

2 years ago

0.2.5

2 years ago

0.2.4

2 years ago

0.2.3

2 years ago

0.2.2

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.1.16

2 years ago

0.1.15

2 years ago

0.1.14

2 years ago

0.1.13

2 years ago

0.1.12

2 years ago

0.1.11

2 years ago

0.1.10

2 years ago

0.1.9

2 years ago

0.1.8

2 years ago

0.1.7

2 years ago

0.1.6

2 years ago

0.1.5

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago