Skip to main content

Metadata Reader

import type { MetadataReader } from '@caffeine-projects/dicaf'

MetadataReader

type MetadataReader = (key: Key) => Partial<Binding>

A function called once per binding registration, after decorator metadata is collected. Its return value is merged over the decorator-derived binding config — fields returned by the reader take precedence over decorator values.

Passed as the metadataReader option in the DiCaf constructor:

const di = new DiCaf({ metadataReader: myReader })

See container options for the full options table.

When to use

MetadataReader is an integration point for bridging external metadata sources into DiCaf. Common use cases:

  • Reading scope or profile overrides from a configuration file or environment
  • Importing binding metadata from another framework's annotation system
  • Applying organisation-wide defaults based on naming conventions

Merge semantics

The returned Partial<Binding> is spread over the binding built from decorators. Any field you return overwrites the decorator value for that binding; omitted fields are left unchanged.

// decorator says SINGLETON; reader says TRANSIENT — TRANSIENT wins
const reader: MetadataReader = key => {
if (scopeOverrides.has(key)) {
return { scopeId: scopeOverrides.get(key) }
}
return {}
}

Example — scope overrides from config

import { Scopes, type MetadataReader } from '@caffeine-projects/dicaf'

const overrides = new Map<unknown, symbol>([
[UserService, Scopes.TRANSIENT],
[AuditLogger, Scopes.REQUEST],
])

const reader: MetadataReader = key => {
const scopeId = overrides.get(key)
return scopeId ? { scopeId } : {}
}

const di = new DiCaf({ metadataReader: reader })

Useful Binding fields to override

FieldTypeSet by decorator
scopeIdIdentifier@Lifetime
profilesSet<Identifier>@Profile
namesIdentifier[]@Named
lazyboolean@Lazy
primaryboolean@Primary
fallbackboolean@Fallback
conditionalsConditional[]@ConditionalOn

Returning factory-level fields (factory, injections, injectionResolvers) from a reader is possible but unusual — prefer the fluent binder API for those.