Usage no npm install needed!

<script type="module">
  import expressAdrDependencyInjectionTypescript from '';


Express ADR Dependency Injection Typescript


This package is a dependency injection for express with typescript using decorators and the Action–Domain–Responder pattern.

Getting Started


Use my CLI to create the application. Instead of "myFolderName" you can add "." to install it in the current directory. Always use npx to use the latest version of the CLI.

npx eadit-cli create myFolderName

Template Check

You will be asked to choose a template. For this one you have to select Express

? What template do you want? (Use arrow keys)
❯ Express

Path Check

You will get the following question:

? Is the path correct? ('/my/path/to/application') (Y/n)

If the path is correct respond with Y or press Enter

Yarn Check

If you have Yarn installed, the CLI will ask if you want to use it, if you say N npm will be used.

? Yarn was detected on your system, do you want to use Yarn? (Y/n)

Dependency Selector

For the next part you can choose if you need more dependencies (They will be automaticly injected). Question 2

Dialect Selector (Only for Sequelize) and complete extra information

If you choose Sequelize, you will also be asked to choose which dialect you want and to complete the connection information. Question 3

Check if directory is empty

If the directory you want to create the application is not empty, you will be asked if you want to remove all files from it. If you don't remove the files the project will not be created.

? The current directory is not empty, do you want to clear it? (y/N)


After everything is installed, you should see the following output. Final

About Action–Domain–Responder

  • The action takes HTTP requests (URLs and their methods) and uses that input to interact with the domain, after which it passes the domain's output to one and only one responder.
  • The domain can modify state, interacting with storage and/or manipulating data as needed. It contains the business logic.
  • The responder builds the entire HTTP response from the domain's output which is given to it by the action.
  • The entity is the model for the database

Project structure


# Here you define the tests, there are default tests defined.

- /**tests**

- /actions

# Here you define the route and the methods (get, post, put, delete)

# Are automatically injectetd!

- - action.ts

- /app

# Here you start the server (app.listen) and other checks before/after starting.

- - Server.ts

- /domain
- - /entities

# Here you define the entiry (They are accessed with @Retrive('Entity.NAME') or from your ORM)

# Are automatically injectetd!

- - - entity.ts

# Here you define the domain (They are accessed with @Retrive('Domain.NAME'))

# Are automatically injectetd!

- - domain.ts

- /middlewares

# Here you define middlewares (as classes).

# You inject them manually

- - middleware.ts


# In public (depends on the Configuration made in index.ts) you have the front-end,

# all routes point to index.html (i made it so it can work with React)

- - index.html

- /responders

# Here you define the domains (They are accessed with @Retrive('Responder.NAME'))

# Are automatically injectetd!

- - responder.ts

# Here you inject classes, middlewares, variables, functions, server, router, etc.

# And you have to call Injector.ready(); when you finished all your injections.

- index.ts


    root: __dirname,
    restPrefix: '/api',
    debug: {
      log: console.log,
      error: console.error
    renderEngine: {
      path: '/',
      directory: ['public']
  } as Configuration,

Entity Model

This model is for Mongoose.

export default class UserEntity implements InjectedEntity {
  private mongoose?: MongooseClass;

  async onLoad(): Promise<void> {
    if (!this.mongoose) {

    const { ObjectId } = Schema as any;

      new Schema({
        id: ObjectId,
        email: {
          type: String,
          min: 3,
          max: 255,
          required: true
        password: {
          type: String,
          min: 8,
          required: true

Responder Model

import { Inject } from 'express-adr-dependency-injection-typescript/lib/Injector';
import { Responder } from 'express-adr-dependency-injection-typescript/lib/Router';
import { Response } from 'express';

export default class DemoResponder {
  public success(res: Response) {
    return res.status(200).json({
      success: true

  public demo(res: Response, status: number, output: any) {
    return res.status(status).json(output);

Middleware Model

import { Request, Response, NextFunction } from 'express';
import {
} from 'express-adr-dependency-injection-typescript/lib/Injector';

export default class AuthentificationMiddleware implements MiddlewareClass {
  public async middleware(
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<any> {
    (req as any).myData = 'My custom request data!';
    return next();

Action Model

import {
} from 'express-adr-dependency-injection-typescript/lib/Router';
import {
  Request as ExpressRequest,
  Response as ExpressResponse
} from 'express';
import { Retrive } from 'express-adr-dependency-injection-typescript/lib/Injector';

import DemoResponder from '../responders/DemoResponder';
import DemoDomain from '../domain/DemoDomain';

@Action('/demo', ['MiddlewareHere'])
export default class DemoAction {
  private responder?: DemoResponder;

  private domain?: DemoDomain;

  @Get('/demo1', ['MiddlwareHere'])
  public findAll(
    @Request req: ExpressRequest,
    @Response res: ExpressResponse
  ): any {
    return res.send({
      success: true,
      test: (req as any).myData

  public async saveX(
    @Request req: ExpressRequest,
    @Response res: ExpressResponse
  ): Promise<any> {
    const dataFromDatabase = await this.domain!.test('parameter from action');
    return this.responder!.demo(res, 201, dataFromDatabase);

  public async deleteY(
    @Request req: ExpressRequest,
    @Response res: ExpressResponse
  ): Promise<any> {
    return this.responder!.success(res);

Domain Model

import { Inject } from 'express-adr-dependency-injection-typescript/lib/Injector';
import { Domain } from 'express-adr-dependency-injection-typescript/lib/Router';

export default class DemoDomain {
  public async test(someParameter: string) {
    return {
      success: true,
      data: 'Data from database',

Server.ts Example

import {
} from 'express-adr-dependency-injection-typescript/lib/Injector';
import { Application } from 'express';
import { Configuration } from 'express-adr-dependency-injection-typescript/lib/Configuration';

export default class Server implements InjectedClass {
  private application?: Application;

  private config?: Configuration;

  private middlewares?: any;

  public async onReady(): Promise<void> {
    try {
      if (!this.application || !this.config) {

      const log = this.config.debug.log ?? console.log;

      this.application.listen(4000, '', async () => {
        log('Server started %o', '');
    } catch (e) {
      const error = this.config?.debug.error ?? console.error;