1.1.7 • Published 14 days ago

ts-request-mediator v1.1.7

Weekly downloads
-
License
ISC
Repository
github
Last release
14 days 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

14 days ago

1.1.6

15 days ago

1.1.5

15 days ago

1.1.4

17 days ago

1.0.62

23 days ago

1.0.61

23 days ago

1.0.60

23 days ago

1.0.63

22 days ago

1.1.1

22 days ago

1.1.0

22 days ago

1.1.3

21 days ago

1.1.2

21 days ago

1.0.59

23 days ago

1.0.55

24 days ago

1.0.54

24 days ago

1.0.53

24 days ago

1.0.58

24 days ago

1.0.57

24 days ago

1.0.56

24 days ago

1.0.49

26 days ago

1.0.50

26 days ago

1.0.52

26 days ago

1.0.48

30 days ago

1.0.47

1 month ago

1.0.46

1 month ago

1.0.45

1 month ago

1.0.44

1 month ago

1.0.43

1 month ago

1.0.42

1 month ago

1.0.39

1 month ago

1.0.38

1 month ago

1.0.40

1 month ago

1.0.41

1 month ago

1.0.37

1 month ago

1.0.36

1 month ago

1.0.35

1 month ago

1.0.34

1 month ago

1.0.29

1 month ago

1.0.28

1 month ago

1.0.33

1 month ago

1.0.32

1 month ago

1.0.31

1 month ago

1.0.30

1 month ago

1.0.27

2 months ago

1.0.26

2 months ago

1.0.25

2 months ago

1.0.24

2 months ago

1.0.22

2 months ago

1.0.20

2 months ago

1.0.23

2 months ago

1.0.19

2 months ago

1.0.18

2 months ago

1.0.17

2 months ago

1.0.16

2 months ago

1.0.15

2 months ago

1.0.9

2 months ago

1.0.11

2 months ago

1.0.10

2 months ago

1.0.14

2 months ago

1.0.13

2 months ago

1.0.12

2 months ago

1.0.8

3 months ago

1.0.7

3 months ago

1.0.6

3 months ago

1.0.5

3 months ago

1.0.4

3 months ago

0.10.3

3 months ago

1.0.2

3 months ago

1.0.1

3 months ago

1.0.0

3 months ago

1.0.3

3 months ago

0.10.1

3 months ago

0.10.2

3 months ago

0.10.0

3 months ago

0.9.45

3 months ago

0.9.46

3 months ago

0.9.44

3 months ago

0.9.43

5 months ago

0.8.9

12 months ago

0.8.5

12 months ago

0.8.4

12 months ago

0.8.7

12 months ago

0.8.6

12 months ago

0.9.41

8 months ago

0.9.42

8 months ago

0.9.40

8 months ago

0.9.34

8 months ago

0.9.8

11 months ago

0.9.35

8 months ago

0.9.7

11 months ago

0.9.36

8 months ago

0.9.37

8 months ago

0.9.9

11 months ago

0.9.30

8 months ago

0.9.31

8 months ago

0.9.32

8 months ago

0.9.33

8 months ago

0.9.38

8 months ago

0.9.39

8 months ago

0.9.23

10 months ago

0.9.24

10 months ago

0.9.25

10 months ago

0.9.26

9 months ago

0.9.20

10 months ago

0.9.21

10 months ago

0.9.22

10 months ago

0.9.27

8 months ago

0.9.28

8 months ago

0.9.29

8 months ago

0.8.1

12 months ago

0.8.3

12 months ago

0.8.2

12 months ago

0.9.12

10 months ago

0.9.13

10 months ago

0.9.14

10 months ago

0.9.15

10 months ago

0.9.10

10 months ago

0.9.11

10 months ago

0.9.16

10 months ago

0.9.17

10 months ago

0.9.18

10 months ago

0.9.19

10 months ago

0.8.0

12 months ago

0.7.40

12 months ago

0.7.39

12 months ago

0.7.38

12 months ago

0.7.37

12 months ago

0.7.36

12 months ago

0.7.35

12 months ago

0.7.34

12 months ago

0.7.33

12 months ago

0.7.32

12 months ago

0.7.31

12 months ago

0.7.30

12 months ago

0.7.29

12 months ago

0.7.28

12 months ago

0.7.27

12 months ago

0.7.26

12 months ago

0.7.25

12 months ago

0.7.24

12 months ago

0.7.23

12 months ago

0.7.22

1 year ago

0.7.21

1 year ago

0.7.20

1 year ago

0.7.19

1 year ago

0.7.18

1 year ago

0.7.17

1 year ago

0.7.16

1 year ago

0.7.15

1 year ago

0.7.14

1 year ago

0.7.13

1 year ago

0.7.12

1 year ago

0.7.11

1 year ago

0.7.10

1 year ago

0.7.9

1 year ago

0.7.8

1 year ago

0.7.7

1 year ago

0.7.6

1 year ago

0.7.5

1 year ago

0.7.4

1 year ago

0.7.3

1 year ago

0.7.0

1 year ago

0.6.0

1 year ago

0.5.0

1 year ago

0.4.0

1 year ago

0.3.3

1 year ago

0.3.2

1 year ago

0.3.1

1 year ago

0.3.0

1 year ago

0.2.31

1 year ago

0.2.30

1 year ago

0.2.29

1 year ago

0.2.28

1 year ago

0.2.27

1 year ago

0.2.26

1 year ago

0.2.25

1 year ago

0.2.24

1 year ago

0.2.23

1 year ago

0.2.22

1 year ago

0.2.21

1 year ago

0.2.20

1 year ago

0.2.19

1 year ago

0.2.18

1 year ago

0.2.17

1 year ago

0.2.16

1 year ago

0.2.15

1 year ago

0.2.14

1 year ago

0.2.13

1 year ago

0.2.12

1 year ago

0.2.11

1 year ago

0.2.10

1 year ago

0.2.9

1 year ago

0.2.8

1 year ago

0.2.7

1 year ago

0.2.6

1 year ago

0.2.5

1 year ago

0.2.4

1 year ago

0.2.3

1 year ago

0.2.2

1 year ago

0.2.1

1 year ago

0.2.0

1 year ago

0.1.16

1 year ago

0.1.15

1 year ago

0.1.14

1 year ago

0.1.13

1 year ago

0.1.12

1 year ago

0.1.11

1 year ago

0.1.10

1 year ago

0.1.9

1 year ago

0.1.8

1 year ago

0.1.7

1 year ago

0.1.6

1 year ago

0.1.5

1 year ago

0.1.4

1 year ago

0.1.3

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.0

1 year ago