Stone.jsDocs
Paradigm

Dependency injection

Service providers

A provider is how a capability enters the app. It registers bindings, then boots them once everything is registered. Every adapter and extension is, underneath, a provider, and your own modules attach through the same seam.

#Register, then boot

The two phases must stay separate. register() only declares bindings and must not resolve anything, because other providers may not have registered yet. Once all have, the kernel calls each boot(), where resolving is safe.

app/DataProvider.tsdeclarativeimperative
import { Provider } from '@stone-js/core'

@Provider()
export class DataProvider {
  constructor ({ container, blueprint }) {
    this.container = container
    this.blueprint = blueprint
  }

  // Phase 1: declare bindings. Do not resolve here.
  register () {
    this.container.singleton('db', () => new Db(this.blueprint.get('stone.db')))
    this.container.alias('db', ['database'])
  }

  // Phase 2: everything is registered; resolving is now safe.
  async boot () {
    await this.container.make('db').connect()
  }

  // Optional: skip this provider in contexts where it does not apply.
  mustSkip () {
    return this.blueprint.get('stone.db') === undefined
  }
}
import { defineServiceProvider } from '@stone-js/core'

const DataProvider = ({ container, blueprint }) => ({
  register () {
    container.singleton('db', () => new Db(blueprint.get('stone.db')))
    container.alias('db', ['database'])
  },
  async boot () {
    await container.make('db').connect()
  },
  mustSkip () {
    return blueprint.get('stone.db') === undefined
  }
})

export const providers = [defineServiceProvider(DataProvider, {}, true)]

#The provider contract

MemberTypeDescription
register()() => voidDeclare bindings only. Never resolve here.
boot()() => Promiseable<void>Run once all providers have registered; resolving is safe.
mustSkip()() => Promiseable<boolean>Return true to skip this provider in a context it does not apply to.

#Providers forbid the function form

A provider always needs the container to register into it, so it must be a class or a factory, never a plain function. This is the one place the three forms are restricted, and the restriction is just the definition of what a provider is.


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)