Stone.jsDocs
Paradigm

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.

app/TaskService.tsdeclarativeimperative
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

OptionTypeDefaultDescription
alias*string | string[]·The name(s) the service is bound under and injected by.
singletonbooleanfalseBuild 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.

app/Tasks.tsdeclarativeimperative
@EventHandler('/tasks')
export class TaskController {
  constructor ({ tasks }: { tasks: TaskService }) { this.tasks = tasks }
}
const TaskController = ({ tasks }) => ({
  list: () => tasks.list()
})

Stone.js

Your app exists in every runtime. Until you run it.

An open-source project by Stone Foundation
Created by Mr. Stone (Evens Pierre)