Dependency Injection
When developing, we usually split a complex logic into small ones by creating multiple service classes. Those services usually follow Single responsibility principle to maintain and write unit test easily.
Abyss.ts already built a Inversion of Control (IoC) to archive this technique.
Create a service
We will use class to define our service. Using @Injectable()
decorator to mark it.
ts
// src/products/services/GetService.ts
import { Injectable } from '@abyss.ts/express-runner';
export interface IProductProps {
id: number;
name: string;
}
@Injectable()
export class GetService {
public call(): IProductProps {
return {
id: 1,
name: 'Shirt',
};
}
}
Constructor Injection
Next, we will inject the service to our controller via constructor using decorator @Inject()
.
ts
// src/products/ProductsController.ts
import { Controller, Get, Post, Inject } from '@abyss.ts/express-runner';
import { GetService, type IProductProps } from './services/GetService.ts';
@Controller('products')
export class ProductsController {
constructor(
@Inject(GetService)
private readonly getService: GetService,
) {}
@Get()
public index(): IProductProps[] {
return [
{
id: 1,
name: 'Shirt',
},
];
}
@Post()
public create(): IProductProps {
return this.getService.call();
}
}
NOTE
Since Abyss.ts supports fully esm
, at the moment, TypeScript does not support parameter reflection to auto detect the injection. Ref here. That's why we need to pass the class as @Inject()
parameter.
Lifetime
There are 3 lifetimes for the DI:
- Transient: class will be initialized whenever it is used.
- Scoped: class will be initialized for each request.
- Singleton: class will be initialized once when the application starts.
NOTE
Only Singleton
is supported at the moment.