Configuring the Container
DiCaf accepts an optional options object as its first constructor argument.
All fields are optional — omitting them gives you the defaults shown below.
import { DiCaf } from '@caffeine-projects/dicaf'
const di = new DiCaf({
// options described in this guide
})
defaultScopeId
Default: Scopes.SINGLETON
The scope applied to any binding that does not declare one explicitly.
import { Scopes } from '@caffeine-projects/dicaf'
const di = new DiCaf({ defaultScopeId: Scopes.TRANSIENT })
Every binding in this container is transient unless it explicitly sets
@Lifetime(Scopes.SINGLETON) or calls .scope(Scopes.SINGLETON) on the binder.
Built-in scopes: Scopes.SINGLETON, Scopes.TRANSIENT, Scopes.REFRESH, Scopes.REQUEST. See the Scopes reference.
lazy
Default: false
Makes all bindings lazy by default — construction is deferred to the first
get() call instead of happening during init().
const di = new DiCaf({ lazy: true })
await di.init()
// nothing constructed yet
di.get(HeavyService) // constructed here
Individual bindings can opt out with @Lazy(false) or .lazy(false) on the binder.
Priority chain (highest first):
- Binding-level
@Lazy()/.lazy() - Container
lazyoption - Scope default
See the Lazy guide for the full breakdown.
profiles
Default: []
Activates the named profiles. Bindings annotated with @Profile('name') are
only registered when the matching profile is active.
const di = new DiCaf({ profiles: ['production'] })
@Profile('production')
@Injectable()
class S3Storage implements Storage { ... }
@Profile('test')
@Injectable()
class InMemoryStorage implements Storage { ... }
See the Profiles guide.
checks
Default: { scopes: 'compatible-scopes-only', circularReferences: true }
checks.scopes
Controls scope validation at init time. Three modes:
| Mode | Behaviour |
|---|---|
'compatible-scopes-only' | Durable scopes (singleton, container) cannot depend on shorter-lived scopes (transient, request). Reverse is allowed. |
'no-mix' | Every dependency must share the exact scope as its consumer. |
'off' | Validation disabled. |
const di = new DiCaf({
checks: { scopes: 'off' },
})
'compatible-scopes-only' is the practical default — it catches the common
mistake of a singleton holding a transient reference while still allowing
singletons to depend on other singletons.
checks.circularReferences
When true, the container detects circular dependencies at init time and throws
before any instance is created.
const di = new DiCaf({
checks: { circularReferences: false },
})
Disable only if you are intentionally breaking cycles with @Lazy(). Keeping
it enabled surfaces new cycles introduced by future edits.
parent
Default: undefined
Attaches a parent container. When a key is not found in the child, resolution falls through to the parent.
const root = new DiCaf()
await root.init()
const child = root.newChild()
await child.init()
// child.get(SomeService) → looks in child first, then root
Prefer newChild() over passing parent directly — newChild() copies
container-scoped bindings and post-processors automatically.
See the child container section in the Modules guide.
decorators
Default: true
When true, the container calls autoWire() in its constructor, registering
all @Injectable-decorated classes it finds in the global decorator registry.
Set to false for fully manual containers where no decorators are used:
const di = new DiCaf({ decorators: false })
di.bind(Logger).toSelf()
di.bind(UserService).toClass(UserService, [Logger])
await di.init()
metadataReader
Default: undefined
A function (key: Key) => Partial<Binding> called for every binding at
registration time. Its return value is merged into the binding, letting you
inject metadata from an external source (config files, environment variables,
feature flags) without decorators.
const di = new DiCaf({
metadataReader: key => {
if (key === DbConnection) {
return { lazy: true }
}
return {}
},
})
This is an advanced escape hatch. For most cases, decorators and binder options cover the same ground with less ceremony.
All options at a glance
| Option | Type | Default |
|---|---|---|
defaultScopeId | Identifier | Scopes.SINGLETON |
lazy | boolean | false |
profiles | Identifier[] | [] |
checks.scopes | 'compatible-scopes-only' | 'no-mix' | 'off' | 'compatible-scopes-only' |
checks.circularReferences | boolean | true |
parent | Container | undefined |
decorators | boolean | true |
metadataReader | MetadataReader | undefined |