Providers
Providers are injectable services that encapsulate business logic.
Providers are classes decorated with @Injectable() that can be injected into controllers and other providers through dependency injection. They are the primary way to encapsulate business logic and keep controllers thin.
Creating a Provider
The @Injectable() decorator marks a class as available for dependency injection:
import { Injectable } from '@velajs/vela';
@Injectable()
class SpiritsService {
private spirits = [{ name: 'Calcifer' }];
findAll() {
return this.spirits;
}
create(spirit: { name: string }) {
this.spirits.push(spirit);
return spirit;
}
}Registering Providers
Providers must be registered in a module's providers array to be available for injection:
import { Module } from '@velajs/vela';
@Module({
providers: [SpiritsService],
controllers: [SpiritsController],
})
class SpiritsModule {}Constructor Injection
Vela resolves dependencies automatically based on constructor parameter types:
@Controller('spirits')
class SpiritsController {
constructor(private readonly spiritsService: SpiritsService) {}
@Get()
findAll() {
return this.spiritsService.findAll();
}
@Post()
create(@Body() body: { name: string }) {
return this.spiritsService.create(body);
}
}Custom Providers
For more control over how providers are created, use custom provider syntax:
Value Providers
Supply a static value:
@Module({
providers: [
{ provide: 'API_URL', useValue: 'https://api.example.com' },
],
})
class AppModule {}Factory Providers
Use a factory function with optional dependencies:
@Module({
providers: [
{
provide: 'DATABASE',
useFactory: (config: ConfigService) => {
return new Database(config.get('DB_URL'));
},
inject: [ConfigService],
},
],
})
class AppModule {}Alias Providers
Point one token to another:
@Module({
providers: [
SpiritsService,
{ provide: 'ELEMENTAL_SERVICE', useExisting: SpiritsService },
],
})
class AppModule {}Injection Tokens
For non-class tokens, use InjectionToken to create a typed token:
import { InjectionToken } from '@velajs/vela';
const CONFIG = new InjectionToken<AppConfig>('app-config');Use it with custom providers:
@Module({
providers: [
{ provide: CONFIG, useValue: { debug: true, port: 3000 } },
],
})
class AppModule {}Inject it using the @Inject() decorator:
@Injectable()
class AppService {
constructor(@Inject(CONFIG) private config: AppConfig) {}
}Provider Scopes
Control the lifecycle of provider instances with the scope option:
| Scope | Behavior |
|---|---|
Scope.SINGLETON | Single shared instance (default) |
Scope.TRANSIENT | New instance every time it is resolved |
Scope.REQUEST | New instance per incoming request |
@Injectable({ scope: Scope.TRANSIENT })
class TransientService {
constructor() {
// created fresh each time it's injected
}
}
@Injectable({ scope: Scope.REQUEST })
class RequestScopedService {
// unique instance per request lifecycle
}Request-scoped providers use a child container created for each incoming request. Singleton providers are inherited from the parent container.
Controllers
Controllers handle incoming requests and return responses.
Modules
Modules organize the application into cohesive blocks of functionality.
Last updated on