Skip to content

API reference ​

Introduction · Complete tutorial · Server recipes

Use this page to find an API and understand its role. The complete tutorial teaches the concepts with examples; the generated reference provides exact signatures, generic constraints, overloads, parameters, return types, and links to source declarations.

Generated reference ​

Entry pointWhat it exposes
di-bagPortable facade, public types, and structured library errors.
di-bag/nodeThe same API with Node/Bun native-Promise detection configured.

Start with the DiBagApi, Builder, and Bag. The same builder seals a reusable Module. The reference represents these type-only exports as interfaces; construct values through DiBag.

The generated Markdown is committed alongside the source. CI compares it with fresh output and verifies public export and callable-overload coverage against the TypeScript compiler. See documentation maintenance for how to regenerate it.

API at a glance ​

Import DiBag and the error classes from di-bag. On Node, Bun, and Deno it detects native Promises itself; elsewhere see portable mode. di-bag/node is the explicit Node/Bun form. Both entries expose the same methods and types. Each table links to explanations and examples in the tutorial; the server guide puts them into an application.

Configure and describe services ​

These methods are available on DiBag and every derived facade. A provider is a reusable declaration; creating one does not acquire a service.

MethodResult and purpose
createBuilder()Create an empty immutable builder that can build a bag or seal a module.
withConfiguration({ runtime?, observers? })Return a new facade; inherit omitted runtime options and append the ordered observer array.
fromFactory(create, options?)Describe a named-dependency factory; acquisitionMode defaults to auto. Add context: 'acquisition' to supply the owner's cancellation context.
fromSyncFactory(create, options?)fromFactory with acquisitionMode: 'raw' fixed and a Promise or thenable output rejected at compile time: the portable synchronous form.
fromAsyncFactory(create, options?)fromFactory with acquisitionMode: 'nativePromise' fixed and a non-Promise output rejected: the portable asynchronous form; withDisposal receives the fulfilled value.
token(key).of<Service>()Create a typed token from a canonical unique symbol.
fromFunction(dependencies, fn, options?)Inject a tuple of tokens/references into a positional callback, checking its actual optional/rest parameter tuple. Write selected but unused parameters explicitly.
fromClass(dependencies, Constructor, options?)Adapt an existing constructor.
optional(token) / lazy(token) / all(token)Supply an optional value, lazy lookup, or ordered collection through a positional dependency tuple.
fromPlugin(dependencies, descriptor, options)Validate a selected plugin with explicit acquisitionMode: 'raw' or 'nativePromise' and a synchronous output validator.
withDisposal(registration, dispose)Accept cleanup ownership of that stage's acquired value.
withLifetime(registration, lifetime, options?)Select root, scoped, or transient; only root accepts allowScopedDependencies.
withMetadata(registration, { static?, dynamic? })Attach registration metadata, acquisition metadata, or both. Dynamic options require mode and synchronous describe.
transformService(registration, { mode, transform, acquisitionMode? })Expose a transformed service, retaining earlier ownership; output acquisition options apply only to direct mode.

direct passes the exact source output and preserves the callback result. awaited waits for the source and exposes a native Promise. Transformation callbacks may return Promises. Metadata callbacks must synchronously return plain object records; direct metadata preserves its source acquisition policy. Static-only metadata preserves the source output. Each dynamic annotation appends one ordered metadata presence frame; no metadata or transformation adds ownership.

Build and reuse a graph ​

Builder operations return a new builder. Keep the returned value or chain the next call; they do not mutate the original.

MethodAvailable onPurpose
register(registrations)BuilderAdd new named factories; duplicate keys reject.
register(token, registration)BuilderBind a typed token.
replace(nameOrToken, registration)BuilderReplace one existing registration while checking its consumers and token contract.
alias(destination, target)BuilderAdd another name or token lookup for an existing service.
contribute(token, registration)BuilderAppend an ordered contribution.
installModule(module)BuilderInstall a sealed module with private services and public exports; modules nest.
build()BuilderCheck graph completeness and return a lazy bag.
buildAndStart(keys, options?)BuilderReturn a promise for a fresh bag after selected services are ready.
buildModule(keys, { label? })BuilderSeal the graph as a module and choose its public names and tokens; unmet dependencies become requirements. A label names private bindings <label>/<key> in diagnostics.
verifyGraph()BuilderRuntime no-op whose return type is void only when the graph would build.
renameExport(oldName, newName)Sealed ModuleReturn a module view with one string-named export renamed.

There is one builder. build() requires a complete graph; buildModule(keys) accepts an incomplete one and records the gaps as requirements of the module. Modules do not resolve services or have a close method. Installing a module gives its acquisitions an owning bag and fresh private identities at every nesting depth.

Use and close a bag ​

MethodPurpose
resolve(nameOrToken)Lazily acquire a service, preserving its inferred return type.
resolveAll(token)Resolve the ordered contributions as a readonly array.
inspect(nameOrToken)Copy metadata and acquisition state without resolving.
inspectAll(token)Inspect contribution descriptions and attempts without resolving.
inspectGraph()Describe every binding, contribution group, and observed edge without resolving.
createScope()Create a tracked child scope.
createScope({ share: keys })Create a child that explicitly borrows selected parent acquisitions.
createScope(keys, overrides, options?)Create a child with checked replacements and optional disjoint share selection.
fork()Create an independent bag with fresh instances.
fork(keys, overrides)Create an independent bag with selected replacements.
close()Return the shutdown promise; stop new resolutions, drain work, and dispose owned resources. Repeated calls share the same promise.
close({ timeoutMs?, signal? })Start the same cleanup but stop waiting at the deadline or on abort with DiBagCloseCancelledError.

Errors and recovery ​

Every library-created message has the form <code>: <message>; see https://dany-fedorov.github.io/di-bag/agent/errors.html#<code-slug>, where the slug is the code lower-cased with _ replaced by -. For example: DI_BAG_CYCLE: cycle: a -> b -> a; see https://dany-fedorov.github.io/di-bag/agent/errors.html#di-bag-cycle. The errors page has one section per code and per compile-time message family.

The specialized error classes below are runtime exports from both di-bag and di-bag/node. Each extends the built-in Error family and has a corresponding name. Catch them with instanceof when choosing a recovery path.

ErrorWhen it appearsPublic information
DiBagCleanupErrorclose() finishes attempting cleanup and one or more disposers failed.Extends AggregateError; errors contains the original errors, and readonly failures associates each with acquisitionId, bindingId, label, and error.
DiBagPluginValidationErrorA plugin descriptor or acquired output fails the plugin boundary checks.phase is 'descriptor' or 'output'; reason describes the rejection.
DiBagStartupErrorSelected startup acquisition fails and rollback has completed.cause is the acquisition error; cleanupFailures contains disposal failures; cleanupError retains the complete cleanup error when present.
DiBagStartupCancelledErrorAn external signal or startup deadline interrupts startup.reason is 'aborted' or 'timeout'; cause retains the cancellation reason; cleanupPromise is a Promise<void> for eventual shutdown.
DiBagCloseCancelledErrorclose({ timeoutMs, signal }) stops waiting before cleanup finishes.code is DI_BAG_CLOSE_TIMEOUT or DI_BAG_CLOSE_ABORTED; details.pending lists unfinished disposer labels and details.acquiring pending acquisitions; cleanupPromise settles when cleanup finishes.

Given an existing application bag named app:

ts
import { DiBagCleanupError } from 'di-bag';

try {
  await app.close();
} catch (error) {
  if (error instanceof DiBagCleanupError) {
    for (const failure of error.failures) {
      console.error(failure.label, failure.error);
    }
  }
  throw error;
}

Constructors are new DiBagCleanupError(failures), new DiBagPluginValidationError(phase, reason), new DiBagStartupError(cause, cleanupFailures, cleanupError?), new DiBagStartupCancelledError(reason, cause, cleanupPromise), and new DiBagCloseCancelledError(reason, cause, cleanupPromise, progress, timeoutMs?). Applications usually catch errors created by the library rather than constructing them.

Factory errors and transformation errors retain their original identity on resolution. Library-created failures expose stable DI_BAG_* codes and frozen structured details; inspect those fields instead of parsing message text. Observer callback failures are delivered to the observer's onError callback and do not become service or shutdown failures. DI_BAG_INVALID_DEPENDENCY_ACCESS reports enumeration or in checks on a factory's dependency object; its details.consumer names the factory.

Exported TypeScript types ​

All names in this section are type-only exports from di-bag and di-bag/node. Use import type for them. They provide annotations and preserve contracts in generated declarations; they do not provide unchecked runtime constructors.

For application code, prefer inferred values and typeof or ReturnType when passing a graph across a module boundary:

ts
import type { ProviderOutput, TokenService } from 'di-bag';

type Clock = TokenService<typeof clock>;
type Stamp = ProviderOutput<typeof stamp>;
type Application = typeof app;

These names refer to the clock, stamp registration, and app in the tutorial’s typed-token example. Shorter Bag, Module, or Provider annotations cannot erase retained private-consumer, token, lifetime, or ownership contracts.

Application-facing types ​

ExportsPurpose
DiBagApiThe complete DiBag method surface, including configured and observed facades.
ConfigurationOptionsRuntime classification and observer options for withConfiguration.
Builder, BagA checked immutable builder and a resolving/owning bag.
ModuleA sealed export view of a builder graph, installable in other builders.
Registration, FactoryWithDisposalAccepted registration shapes and an owned factory description.
ProviderA provider description retaining its factory, metadata, frames, graph contracts, and acquired-value type.
AcquisitionMode, RuntimeOptionsAcquisition mode literals and the isNativePromise configuration callback.
LifetimeThe 'root', 'scoped', and 'transient' caching choices.
AcquisitionContext, ContextualFactoryFactory cancellation context (signal) and the adapted contextual factory signature.
StartupOptionsOptional signal, timeoutMs, and startupOrder fields for buildAndStart.
ScopeOptionsThe checked share selection accepted by createScope.
Token, TokenBase, TokenKey, TokenServiceTyped token identity, its common handle type, and key/service projections.
OptionalDependency, LazyDependency, CollectionDependency, DependencyReferenceThe token reference forms accepted in positional dependency tuples.
CompositionArguments, CompositionFunctionPositional argument compatibility and callback signatures for function/constructor adaptation.
Presence{ present: false } or { present: true, value }, including present undefined.
AcquisitionMetadataPresence, AcquisitionSnapshot, RegistrationSnapshotInspection frames, acquisition state, and registration metadata snapshots.
GraphSnapshot, BindingSnapshotThe frozen result of inspectGraph() and its per-binding entries.
CleanupFailureThe detached acquisition identity, label, and original cleanup error.
DiBagErrorCode, DiBagDiagnosticStable library error codes and their structured diagnostic fields.
ObserverOptions, ObserverCallback, ObserverErrorCallbackObserver configuration and its event/failure callbacks.
LifecycleEvent, ObserverFailure, ScopeEventFields, AcquisitionEventFieldsDiscriminated lifecycle events and observer failure context.
PluginAcquisitionMode, PluginOptions, PluginOutputValidator, PluginProviderPlugin mode, validation options, output predicate, and resulting provider.
PluginProviderFactoryThe callable type of DiBag.fromPlugin; use it directly as a type.
CompositionReportThe compile-time verdict for a builder: void when buildable, otherwise the build() failure with details.
DiBagPolicyEmpty interface for project-wide compile-time switches; augment with structuralThenables: 'allow' to relax the thenable check.

Provider and module projections ​

ExportsPurpose
ProviderFactory, ProviderOutput, ProviderAcquiredValue, ProviderNamedDependenciesExtract the factory, exposed result, acquired value, and named requirements from a registration. Output and acquired value can differ across async boundaries.
ProviderRegistrationMetadata, ProviderAcquisitionMetadataExtract static metadata and the tuple of acquisition metadata frames.
ProviderGraphContractRetain a provider's token and other graph obligations.
ProviderRequiredTokens, ProviderOptionalTokens, ProviderCollectionTokensExtract required/lazy, optional, and collection token requirements.
ModuleExportedServices, ModuleRequiredServicesExtract the readonly service exports and external requirements of a sealed module.
ModuleConstraintsCompute retained private-consumer and lifetime constraints for a registration map and public selection.
SealedConstraints, ModuleSealedConstraintsRe-scope constraints retained from installed modules when a builder seals; the complete constraint set of a sealed module.
PublicProviders, ModulePublicProvidersPreserve provider contracts when projecting public module registrations.
RenamedRepresent the checked renaming of a module's public view.

Graph composition support types ​

These exports support reusable generic helpers and portable declaration output. Most applications can let the builder infer them. They express compile-time contracts; they do not perform runtime validation.

ExportsPurpose
ServicesOfMap registrations to their exposed service types.
RegistrationEntries, RegistrationsFromEntriesConvert between a registration map and its entry representation.
OverrideRegistrations, SelectedRegistrationsModel merged registration maps and selected override registrations.
CheckDependencyCompatibility, CheckDependencyCompletenessCheck dependency shape compatibility and graph completeness.
Selection, Overrides, OverrideFactoryContextValidate selections and replacement compatibility while preserving contextual inference.
TokenBinding, TokenMember, TokenDependencyContractRetain typed bindings, validate token membership, and represent token obligations.
ReboundProviders, ReboundSelection, SelectionKeyPreserve token bindings across replacement and map selections to their string/symbol keys.
AliasRegistration, AliasEntries, AliasOutputModel an alias registration, its graph entries, and its exposed result.
Contribution, ContributionConstraintDescribe an ordered contribution and its retained requirements.
ModuleContributions, ModuleContributionConstraintsPreserve contributions and their requirements in modules.
BuilderContributeThe generic contribute signature on the builder.
DisjointScopeSelectionEnforce separate override and sharing selections.
UnsharedAliases, ScopedAliases, SharedAliasProvidersPreserve alias contracts as scopes inherit or explicitly share services.
CheckedLifetimes, CheckedScopeLifetimesCheck root capture and lifetime compatibility in completed graphs and scope overrides.
LifetimeObligation, ReachCompact seal-time lifetime records a module retains instead of its private registrations.

The authoritative export lists are src/index.ts and src/node.ts. Internal helpers in other source files are not package exports.

Boundaries ​

  • Token maps and dependency parameters must have finite string keys. Index signatures, including open template keys, cannot prove that tokens exist.
  • Bags are created through checked builders and forks. Bag is exported as a type only; there is no public unchecked constructor.
  • Parameters may be omitted or be a single object type. Optional dependency properties still require providers. Union, callable, and symbol-keyed dependency parameter types are rejected.
  • Dependency proxies support named property reads. Do not enumerate, spread, or use rest destructuring on them: parameter types are erased at runtime, so the bag cannot enumerate a particular factory's declared requirements.
  • Use a single, explicit factory signature. TypeScript utility types see the last signature of overloaded functions; arbitrary overload behavior cannot be inferred. As with other TypeScript APIs, casts and unchecked JavaScript can bypass compile-time checks; runtime resolution still checks missing tokens.
  • JavaScript output targets ES2022. The CommonJS package supports Node require and ESM named imports, and browsers through a bundler. Bun is only needed to run the development tests. The supported compiler floor and development type checks use TypeScript 6.0.3.

Usage topics ​

The detailed examples live in the complete tutorial. These links also preserve existing bookmarks into the earlier combined guide.

Compose services ​

Read the tutorial section.

Reuse named modules ​

Read the tutorial section.

Use typed tokens for explicit positional injection ​

Read the tutorial section.

Adapt classes and positional functions ​

Read the tutorial section.

Declare optional and lazy dependencies ​

Read the tutorial section.

Give a dependency another lookup name ​

Read the tutorial section.

Compose an ordered collection ​

Read the tutorial section.

Attach metadata and inspect without resolving ​

Read the tutorial section.

Observe lifecycle transitions ​

Read the tutorial section.

Admit an application-selected plugin ​

Read the tutorial section.

Async edges are explicit ​

Read the tutorial section.

Project services explicitly ​

Read the tutorial section.

Attach cleanup with withDisposal ​

Read the tutorial section.

Start selected services and cancel cooperatively ​

Read the tutorial section.

Choose root, scoped or transient caching ​

Read the tutorial section.

Create tracked child scopes ​

Read the tutorial section.

Fork for scopes and tests ​

Read the tutorial section.

WBS-shaped ownership example ​

Read the tutorial section.

Represent acquisition values and metadata natively ​

Read the tutorial section.

Ordinary services. Checked composition. Explicit ownership.