Dependency injection
Services
A service is a unit of logic the container can build and inject. Register it once, give it a name, and any handler or other service can ask for it by that name. This is how the domain declares what it needs without ever constructing it.
#Registering a service
Mark a class with @Service (or register a defineService). The alias is the name it is bound under and the name others destructure to receive it. Injection is by alias, not by type, because Stone.js uses no reflect-metadata.
import { Service } from '@stone-js/core'
@Service({ alias: 'tasks', singleton: true })
export class TaskService {
// Other services arrive by their alias, destructured.
constructor ({ db, logger }: { db: Db, logger: ILogger }) {
this.db = db
this.logger = logger
}
list () { return this.db.query('tasks') }
}import { defineService } from '@stone-js/core'
const TaskService = ({ db, logger }) => ({
list: () => db.query('tasks')
})
export const services = [
defineService(TaskService, { alias: 'tasks', singleton: true }, true)
]#Service options
| Option | Type | Default | Description |
|---|---|---|---|
| alias* | string | string[] | · | The name(s) the service is bound under and injected by. |
| singleton | boolean | false | Build once per container (per event) and cache; otherwise built on each resolution. |
#Injection resolves by alias
Because there is no type reflection, a constructor receives a single object of resolved bindings, and you destructure the aliases you want. The names must match the aliases you registered.
@EventHandler('/tasks')
export class TaskController {
constructor ({ tasks }: { tasks: TaskService }) { this.tasks = tasks }
}const TaskController = ({ tasks }) => ({
list: () => tasks.list()
})