Skip to content

DI Bag API / index / Container

Interface: Container<ServiceRegistrations extends Registrations, Constraints extends NeedConstraint = never> ​

Defined in: di-bag.ts:114

A resolving container with lazy acquisition, caching, and independent resource ownership.

Create containers through DiBagApi.createBuilder followed by Builder.buildContainer, and make services ready ahead of use with Container.ensureServicesReady; the class is exported as a type and has no public constructor.

See ​

https://dany-fedorov.github.io/di-bag/agent/api-card.html#container

Type Parameters ​

Type ParameterDescription
ServiceRegistrationsThe map from each public service name or token symbol to its provider.
ConstraintsThe requirements, contributions and lifetime obligations that installed modules retain on this graph.

Methods ​

close() ​

ts
close(options?: CloseOptions): Promise<void>;

Defined in: di-bag.ts:398

Close this container, drain in-flight work, and dispose owned resources once. Dependents are disposed before dependencies; remaining independent acquisitions use reverse acquisition order. Without options the promise waits for disposal however long it takes, and repeated calls return the same promise. With waitTimeoutMs or abortSignal, disposal starts the same way but the returned promise stops waiting when either fires; child and independent containers accept the same options. Close every derived container you create; a parent closes its live children, never independent containers.

Parameters ​

ParameterDescription
options?An optional deadline and abort signal bounding the wait, not the disposal.

Returns ​

The shared shutdown promise, or a bounded wait on it when options are given.

Throws ​

DiBagDisposalError (DI_BAG_DISPOSAL_FAILED) when one or more disposers fail after all disposal is attempted; DI_BAG_CLOSE_FAILED for other shutdown failures; DiBagCloseCancelledError (DI_BAG_CLOSE_TIMEOUT or DI_BAG_CLOSE_ABORTED) when the wait stops first, naming unfinished disposers in details.disposersStillRunning; DI_BAG_INVALID_ARGUMENT for malformed options.

Example ​

ts
const container = DiBag.createBuilder().withServices({ value: () => 1 }).buildContainer();
await container.close({ waitTimeoutMs: 10_000, abortSignal: AbortSignal.timeout(15_000) });

createChildContainer() ​

Call Signature ​

ts
createChildContainer(options?: CreateChildContainerOptions<ServiceRegistrations, readonly [], Constraints>): Container<UnsharedAliases<ServiceRegistrations>, Constraints>;

Defined in: di-bag.ts:278

Create a tracked child container with fresh ownership for unshared services. Share selected non-transient parent acquisitions through the optional options object. To replace services, pass selected keys and providers first, then the sharing options.

Parameters ​
ParameterDescription
options?-
Returns ​

A child owned by this container; closing the parent closes the child first.

Throws ​

DI_BAG_INVALID_ARGUMENT for malformed arguments; DI_BAG_CONFLICTING_SERVICE_SELECTION when one key is shared and replaced or a transient service is shared; DI_BAG_MISSING_REPLACEMENT_PROVIDER for a missing replacement provider; DI_BAG_UNKNOWN_SERVICE_KEY for an unknown selected key; DI_BAG_SINGLETON_REPLACEMENT when a selected inherited provider is singleton; DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad token or kind.

Example ​
ts
const parent = DiBag.createBuilder().withServices({ request: DiBag.providerWithLifetime({
  provider: () => ({ id: 'initial' }), lifetime: 'scoped:one-per-container',
}) }).buildContainer();
const child = parent.createChildContainer(['request'], { request: () => ({ id: 'child' }) });
const request = child.resolve('request');
await child.close();
await parent.close();

Call Signature ​

ts
createChildContainer<const SharedParentServiceKeys extends readonly unknown[]>(options: CreateChildContainerOptions<ServiceRegistrations, SharedParentServiceKeys, Constraints>): Container<ScopedAliases<ServiceRegistrations, ServiceRegistrations, SharedParentServiceKeys>, Constraints>;

Defined in: di-bag.ts:281

Create a tracked child container with fresh ownership for unshared services. Share selected non-transient parent acquisitions through the optional options object. To replace services, pass selected keys and providers first, then the sharing options.

Type Parameters ​
Type ParameterDescription
SharedParentServiceKeys-
Parameters ​
ParameterDescription
options-
Returns ​

A child owned by this container; closing the parent closes the child first.

Throws ​

DI_BAG_INVALID_ARGUMENT for malformed arguments; DI_BAG_CONFLICTING_SERVICE_SELECTION when one key is shared and replaced or a transient service is shared; DI_BAG_MISSING_REPLACEMENT_PROVIDER for a missing replacement provider; DI_BAG_UNKNOWN_SERVICE_KEY for an unknown selected key; DI_BAG_SINGLETON_REPLACEMENT when a selected inherited provider is singleton; DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad token or kind.

Example ​
ts
const parent = DiBag.createBuilder().withServices({ request: DiBag.providerWithLifetime({
  provider: () => ({ id: 'initial' }), lifetime: 'scoped:one-per-container',
}) }).buildContainer();
const child = parent.createChildContainer(['request'], { request: () => ({ id: 'child' }) });
const request = child.resolve('request');
await child.close();
await parent.close();

Call Signature ​

ts
createChildContainer<const ReplacedServiceKeys extends readonly unknown[], ReplacementProviders extends OverrideFactoryContext<ServiceRegistrations, ReplacedServiceKeys, ReplacementProviders>, const SharedParentServiceKeys extends readonly unknown[] = readonly []>(replacedServiceKeys: ReplacedServiceKeys & Selection<ServiceRegistrations, Constraints, ReplacedServiceKeys, 'createChildContainer'>, replacementProviders: ReplacementProviders & ChildReplacementAdmission<ServiceRegistrations, ReplacedServiceKeys> & object & Record<SelectionKey<ReplacedServiceKeys[number]>, ProviderOrFactory> & Overrides<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>, ReplacedServiceKeys, 'createChildContainer'> & CheckDependencyCompatibility<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CheckDependencyCompleteness<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CheckedConstraints<Constraints, OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CompleteConstraints<Constraints, OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CheckedChildContainerLifetimes<NoInfer<ScopedAliases<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>, ServiceRegistrations, SharedParentServiceKeys>>, NoInfer<ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>, WithoutExportObligations<Constraints, SelectionKey<ReplacedServiceKeys[number]>>>, options?: Pick<CreateChildContainerOptions<ServiceRegistrations, SharedParentServiceKeys, Constraints>, 'sharedParentServiceKeys'> & DisjointChildContainerSelection<ReplacedServiceKeys, SharedParentServiceKeys>): Container<ScopedAliases<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>, ServiceRegistrations, SharedParentServiceKeys>, WithoutExportObligations<Constraints, SelectionKey<ReplacedServiceKeys[number]>>>;

Defined in: di-bag.ts:284

Create a tracked child container with fresh ownership for unshared services. Share selected non-transient parent acquisitions through the optional options object. To replace services, pass selected keys and providers first, then the sharing options.

Type Parameters ​
Type ParameterDescription
ReplacedServiceKeys-
ReplacementProviders-
SharedParentServiceKeys-
Parameters ​
ParameterDescription
replacedServiceKeys-
replacementProviders-
options?-
Returns ​

A child owned by this container; closing the parent closes the child first.

Throws ​

DI_BAG_INVALID_ARGUMENT for malformed arguments; DI_BAG_CONFLICTING_SERVICE_SELECTION when one key is shared and replaced or a transient service is shared; DI_BAG_MISSING_REPLACEMENT_PROVIDER for a missing replacement provider; DI_BAG_UNKNOWN_SERVICE_KEY for an unknown selected key; DI_BAG_SINGLETON_REPLACEMENT when a selected inherited provider is singleton; DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad token or kind.

Example ​
ts
const parent = DiBag.createBuilder().withServices({ request: DiBag.providerWithLifetime({
  provider: () => ({ id: 'initial' }), lifetime: 'scoped:one-per-container',
}) }).buildContainer();
const child = parent.createChildContainer(['request'], { request: () => ({ id: 'child' }) });
const request = child.resolve('request');
await child.close();
await parent.close();

createIndependentContainer() ​

Call Signature ​

ts
createIndependentContainer(this: Container<ServiceRegistrations, Constraints> & CheckedLifetimes<UnsharedAliases<ServiceRegistrations>, Constraints>, options?: CreateIndependentContainerOptions<ServiceRegistrations, Constraints>): Container<UnsharedAliases<ServiceRegistrations>, Constraints>;

Defined in: di-bag.ts:312

Create an independent container with fresh instances and no replacements. Pass no argument, undefined, or an empty options object.

Parameters ​
ParameterDescription
this-
options?-
Returns ​

A container with independent acquisition and ownership state.

Throws ​

DI_BAG_INVALID_ARGUMENT for malformed arguments.

Call Signature ​

ts
createIndependentContainer<const ReplacedServiceKeys extends readonly unknown[], ReplacementProviders extends OverrideFactoryContext<ServiceRegistrations, ReplacedServiceKeys, ReplacementProviders>>(replacedServiceKeys: ReplacedServiceKeys & Selection<ServiceRegistrations, Constraints, ReplacedServiceKeys, 'createIndependentContainer'>, replacementProviders: ReplacementProviders & object & Record<SelectionKey<ReplacedServiceKeys[number]>, ProviderOrFactory> & Overrides<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>, ReplacedServiceKeys, 'createIndependentContainer'> & CheckDependencyCompatibility<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CheckDependencyCompleteness<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CheckedConstraints<Constraints, OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CompleteConstraints<Constraints, OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>> & CheckedLifetimes<UnsharedAliases<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>>, WithoutExportObligations<Constraints, SelectionKey<ReplacedServiceKeys[number]>>>): Container<UnsharedAliases<OverrideRegistrations<ServiceRegistrations, ReboundSelection<ServiceRegistrations, ReplacedServiceKeys, SelectedRegistrations<ReplacedServiceKeys, ReplacementProviders>>>>, WithoutExportObligations<Constraints, SelectionKey<ReplacedServiceKeys[number]>>>;

Defined in: di-bag.ts:330

Create an independent container with fresh instances and checked replacements.

Type Parameters ​
Type ParameterDescription
ReplacedServiceKeys-
ReplacementProviders-
Parameters ​
ParameterDescription
replacedServiceKeys-
replacementProviders-
Returns ​

A container with independent acquisition and ownership state.

Throws ​

DI_BAG_INVALID_ARGUMENT for malformed arguments; DI_BAG_MISSING_REPLACEMENT_PROVIDER for a missing replacement provider; DI_BAG_UNKNOWN_SERVICE_KEY for an unknown selected key; DI_BAG_INVALID_PROVIDER for a malformed provider; DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad token or kind.

Example ​
ts
const parent = DiBag.createBuilder().withServices({ clock: () => Date.now() }).buildContainer();
const independent = parent.createIndependentContainer(['clock'], { clock: () => 0 });
const now = independent.resolve('clock');
await independent.close();
await parent.close();

ensureServicesReady() ​

ts
ensureServicesReady<const K extends readonly unknown[]>(serviceKeys: K & Selection<ServiceRegistrations, Constraints, K, 'ensureServicesReady'>, options?: EnsureServicesReadyOptions): Promise<this>;

Defined in: di-bag.ts:371

Make the listed services ready before continuing, then resolve to this same container. Each listed service is acquired now, with whatever its factory reads, and the call waits until it is ready; every other service stays lazy. List the services whose readiness you need before the next line runs, such as a database pool or a cache client. Works on a built container, a child container, and an independent container, and may be called again. A failed factory, an aborted signal, or an elapsed deadline closes this container: a child container closes only itself, never its parent or a service it borrows.

Type Parameters ​

Type ParameterDescription
K-

Parameters ​

ParameterDescription
serviceKeysA finite tuple of existing names or typed tokens to wait for; an empty tuple is valid.
options?An optional abort signal, a deadline for the whole call, and a bound on how many listed keys are acquired at once.

Returns ​

A promise for this container once every listed service is ready.

Throws ​

DiBagServiceReadinessError (DI_BAG_SERVICE_READINESS_FAILED) after this container has closed because a factory failed; DiBagServiceReadinessCancelledError (DI_BAG_SERVICE_READINESS_CANCELLED) promptly on abort or timeout, naming what was still pending; DI_BAG_INVALID_ARGUMENT for malformed keys or options, DI_BAG_UNKNOWN_SERVICE_KEY for an unknown key, and DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad token or kind, all before any factory runs and with this container left open; DI_BAG_CLOSING or DI_BAG_CLOSED after close(). Each arrives as a rejection.

Example ​

ts
const container = await DiBag.createBuilder()
  .withServices({ db: async () => ({ ping: () => true }) })
  .buildContainer()
  .ensureServicesReady(['db'], { totalTimeoutMs: 5_000 });

graphSnapshot() ​

ts
graphSnapshot(): GraphSnapshot;

Defined in: di-bag.ts:257

Describe every resolvable binding and the dependency edges observed so far.

Returns ​

A frozen point-in-time graph snapshot without acquiring services.

Example ​

ts
const container = DiBag.createBuilder().withServices({ greeting: () => 'hello' }).buildContainer();
const labels = container.graphSnapshot().bindings.map(binding => binding.bindingLabel);
await container.close();

resolve() ​

ts
resolve<K extends (keyof ServiceRegistrations & string) | TokenBase>(token: K & ([K] extends [string] ? unknown : SingleServiceTokenMember<ServiceRegistrations, K>)): ServicesOf<ServiceRegistrations>[SelectionKey<K> & keyof ServiceRegistrations];

Defined in: di-bag.ts:146

Resolve a registered service, acquiring it lazily when needed. Scoped and singleton services are cached according to their lifetime; transient services create a new acquisition for each call. Promise-valued services keep their identity. An async factory's service is its Promise; nothing is awaited for you.

Type Parameters ​

Type ParameterDescription
K-

Parameters ​

ParameterDescription
tokenAn existing public string name or typed token.

Returns ​

The service exposed by the selected provider.

Throws ​

DI_BAG_CLOSING or DI_BAG_CLOSED after close(); DI_BAG_INVALID_TOKEN, DI_BAG_WRONG_TOKEN_KIND, or DI_BAG_UNKNOWN_SERVICE_KEY for a bad selection; during acquisition DI_BAG_MISSING_DEPENDENCY, DI_BAG_DEPENDENCY_CYCLE, DI_BAG_LIFETIME_DEPENDENCY, DI_BAG_INVALID_DEPENDENCY_ACCESS, DI_BAG_STRUCTURAL_THENABLE, DI_BAG_INVALID_CLASSIFIER_RESULT, DI_BAG_INVALID_ACQUISITION_METADATA, DI_BAG_PLUGIN_VALIDATION, or the factory's own error.

Example ​

ts
const container = DiBag.createBuilder().withServices({ greeting: () => 'hello' }).buildContainer();
const greeting: string = container.resolve('greeting');

resolveCollection() ​

ts
resolveCollection<T extends CollectionTokenBase>(token: T & CollectionTokenMember<Constraints, T>, ...invalid: [T] extends [never] ? [never] : []): readonly CollectionItem<T>[];

Defined in: di-bag.ts:172

Resolve every contribution for a collection token as a fresh frozen list.

Type Parameters ​

Type ParameterDescription
T-

Parameters ​

ParameterDescription
tokenThe collection token to read.
...invalid-

Returns ​

Contributions in declaration order, or an empty list.

Throws ​

DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad handle or kind; DI_BAG_CLOSING or DI_BAG_CLOSED after close begins; or a contribution's acquisition errors as listed for Container.resolve.

Example ​

ts
const toolsKey = Symbol('tools');
const tools = DiBag.createToken(toolsKey).forCollectionOf<string>();
const container = DiBag.createBuilder().buildContainer();
const names: readonly string[] = container.resolveCollection(tools);

serviceSnapshot() ​

Call Signature ​

ts
serviceSnapshot<ServiceKey extends (keyof ServiceRegistrations & string) | TokenBase>(serviceKey: ServiceKey & ([ServiceKey] extends [string] ? unknown : SingleServiceTokenMember<ServiceRegistrations, ServiceKey>), ...invalid: [ServiceKey] extends [never] ? [never] : []): RegistrationSnapshot<ProviderRegistrationMetadata<ServiceRegistrations[SelectionKey<ServiceKey> & keyof ServiceRegistrations]>, ProviderAcquisitionMetadata<ServiceRegistrations[SelectionKey<ServiceKey> & keyof ServiceRegistrations]>>;

Defined in: di-bag.ts:197

Inspect a service binding through any supported public key without resolving it.

Type Parameters ​
Type ParameterDescription
ServiceKey-
Parameters ​
ParameterDescription
serviceKeyThe public service name or typed token to inspect.
...invalid-
Returns ​

The service snapshot, or one snapshot per collection contribution.

Throws ​

DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad handle or kind.

Example ​
ts
const container = DiBag.createBuilder().withServices({ greeting: () => 'hello' }).buildContainer();
const snapshot = container.serviceSnapshot('greeting');
await container.close();

Call Signature ​

ts
serviceSnapshot<CollectionToken extends CollectionTokenBase>(collectionToken: CollectionToken & CollectionTokenMember<Constraints, CollectionToken>, ...invalid: [CollectionToken] extends [never] ? [never] : []): readonly RegistrationSnapshot<object, readonly unknown[]>[];

Defined in: di-bag.ts:220

Inspect every contribution to a collection without resolving it.

Type Parameters ​
Type ParameterDescription
CollectionToken-
Parameters ​
ParameterDescription
collectionTokenThe typed collection token to inspect.
...invalid-
Returns ​

One service snapshot per collection contribution.

Throws ​

DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad handle or kind.

Example ​
ts
const handlersKey = Symbol('handlers');
const handlers = DiBag.createToken(handlersKey).forCollectionOf<() => void>();
const container = DiBag.createBuilder()
  .withCollectionContribution({ collectionToken: handlers, provider: () => () => {} })
  .buildContainer();
const snapshots = container.serviceSnapshot(handlers);
await container.close();

Call Signature ​

ts
serviceSnapshot<ServiceKey extends (keyof ServiceRegistrations & string) | TokenBase>(serviceKey: ServiceKey & ([
    ServiceKey
] extends [string] ? unknown : [ServiceKey] extends [CollectionTokenBase] ? CollectionTokenMember<Constraints, ServiceKey> : SingleServiceTokenMember<ServiceRegistrations, ServiceKey>), ...invalid: [ServiceKey] extends [never] ? [never] : []): TokenBase extends ServiceKey ? RegistrationSnapshot<object, readonly unknown[]> | readonly RegistrationSnapshot<object, readonly unknown[]>[] : ServiceKey extends CollectionTokenBase ? readonly RegistrationSnapshot<object, readonly unknown[]>[] : RegistrationSnapshot<ProviderRegistrationMetadata<ServiceRegistrations[SelectionKey<ServiceKey> & keyof ServiceRegistrations]>, ProviderAcquisitionMetadata<ServiceRegistrations[SelectionKey<ServiceKey> & keyof ServiceRegistrations]>>;

Defined in: di-bag.ts:224

Inspect a service binding through any supported public key without resolving it.

Type Parameters ​
Type ParameterDescription
ServiceKey-
Parameters ​
ParameterDescription
serviceKeyThe public service name or typed token to inspect.
...invalid-
Returns ​

The service snapshot, or one snapshot per collection contribution.

Throws ​

DI_BAG_INVALID_TOKEN or DI_BAG_WRONG_TOKEN_KIND for a bad handle or kind.

Example ​
ts
const container = DiBag.createBuilder().withServices({ greeting: () => 'hello' }).buildContainer();
const snapshot = container.serviceSnapshot('greeting');
await container.close();

Ordinary services. Checked composition. Explicit ownership.