di-bag 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/AGENTS.md +149 -0
  2. package/README.md +59 -46
  3. package/dist/acquisition-context.d.ts +8 -2
  4. package/dist/acquisition-mode.d.ts +9 -4
  5. package/dist/acquisition-mode.js +25 -7
  6. package/dist/acquisition.d.ts +2 -0
  7. package/dist/acquisition.js +9 -0
  8. package/dist/alias-types.d.ts +12 -3
  9. package/dist/composition-report.d.ts +3 -2
  10. package/dist/composition.d.ts +8 -2
  11. package/dist/contribution-types.d.ts +26 -18
  12. package/dist/dependency-references.d.ts +16 -4
  13. package/dist/di-bag.d.ts +320 -41
  14. package/dist/di-bag.js +86 -14
  15. package/dist/errors.d.ts +115 -8
  16. package/dist/errors.js +113 -12
  17. package/dist/index.d.ts +5 -5
  18. package/dist/index.js +2 -1
  19. package/dist/inspection.d.ts +21 -5
  20. package/dist/lifetime-types.d.ts +281 -180
  21. package/dist/lifetime.d.ts +4 -1
  22. package/dist/module-types.d.ts +87 -30
  23. package/dist/module.d.ts +18 -4
  24. package/dist/module.js +31 -7
  25. package/dist/observers.d.ts +25 -6
  26. package/dist/plugins.d.ts +17 -4
  27. package/dist/provider.d.ts +41 -10
  28. package/dist/provider.js +1 -0
  29. package/dist/registration.d.ts +8 -2
  30. package/dist/registration.js +4 -1
  31. package/dist/runtime.d.ts +12 -3
  32. package/dist/runtime.js +25 -8
  33. package/dist/scope-types.d.ts +20 -5
  34. package/dist/startup.d.ts +19 -1
  35. package/dist/startup.js +72 -11
  36. package/dist/token-types.d.ts +26 -8
  37. package/dist/tokens.d.ts +10 -2
  38. package/dist/tokens.js +2 -0
  39. package/dist/types.d.ts +68 -22
  40. package/docs/agent/api-card.md +337 -0
  41. package/docs/agent/errors.md +1042 -0
  42. package/docs/agent/recipes.md +290 -0
  43. package/package.json +11 -5
@@ -7,13 +7,25 @@ declare class ReferenceBase {
7
7
  declare class DependencyHandle<T extends TokenBase, K extends 'optional' | 'lazy' | 'all'> extends ReferenceBase {
8
8
  readonly [referenceInvariant]: (value: [T, K]) => [T, K];
9
9
  }
10
- /** A positional dependency that yields the token service or `undefined` when unbound. */
10
+ /**
11
+ * A positional dependency that yields the token service or `undefined` when unbound.
12
+ * @see https://dany-fedorov.github.io/di-bag/guides/tutorial.html#declare-optional-and-lazy-dependencies
13
+ */
11
14
  export type OptionalDependency<T extends TokenBase> = DependencyHandle<T, 'optional'>;
12
- /** A positional dependency that yields all contributions for a token as a readonly array. */
15
+ /**
16
+ * A positional dependency that yields all contributions for a token as a readonly array.
17
+ * @see https://dany-fedorov.github.io/di-bag/guides/tutorial.html#compose-an-ordered-collection
18
+ */
13
19
  export type CollectionDependency<T extends TokenBase> = DependencyHandle<T, 'all'>;
14
- /** A positional dependency that yields a function which resolves the token on demand. */
20
+ /**
21
+ * A positional dependency that yields a function which resolves the token on demand.
22
+ * @see https://dany-fedorov.github.io/di-bag/guides/tutorial.html#declare-optional-and-lazy-dependencies
23
+ */
15
24
  export type LazyDependency<T extends TokenBase> = DependencyHandle<T, 'lazy'>;
16
- /** A typed token or one of the positional dependency-reference handles. */
25
+ /**
26
+ * A typed token or one of the positional dependency-reference handles.
27
+ * @see https://dany-fedorov.github.io/di-bag/guides/tutorial.html#adapt-classes-and-positional-functions
28
+ */
17
29
  export type DependencyReference = TokenBase | ReferenceBase;
18
30
  type ReferenceParts<R> = R extends {
19
31
  readonly [referenceInvariant]: (...args: never[]) => [infer T extends TokenBase, infer K];
package/dist/di-bag.d.ts CHANGED
@@ -5,15 +5,15 @@ import { optional, lazy, all } from './dependency-references';
5
5
  import { withDisposal } from './registration';
6
6
  import type { FactoryWithDisposal, Factory, Registration, Registrations } from './registration';
7
7
  import { BindingGraph, BagRuntime } from './runtime';
8
- import type { Module } from './module';
8
+ import type { Module, ModuleOptions } from './module';
9
9
  import type { CompositionReport } from './composition-report';
10
10
  import type { CheckedConstraints, CompleteConstraints, ExternalRequirements, IncrementalConstraints, ModulePublicProviders, ModuleSealedConstraints, NeedConstraint } from './module-types';
11
- import type { CheckedLifetimes } from './lifetime-types';
11
+ import type { CheckedLifetimes, SealAdmission, WithoutExportObligations } from './lifetime-types';
12
12
  import { withLifetime } from './lifetime';
13
13
  import { fromFactory } from './acquisition-context';
14
14
  import type { ScopeOptions, DisjointScopeSelection, UnsharedAliases, ScopedAliases } from './scope-types';
15
15
  import type { CheckedScopeLifetimes } from './lifetime-types';
16
- import type { StartupOptions } from './startup';
16
+ import type { CloseOptions, StartupOptions } from './startup';
17
17
  import { withMetadata, transformService } from './provider';
18
18
  import { fromFunction, fromClass } from './composition';
19
19
  import type { RuntimeContext, RuntimeOptions } from './acquisition-mode';
@@ -24,7 +24,7 @@ import type { PluginProviderFactory } from './plugins';
24
24
  import type { TokenBase, TokenKey, TokenService } from './tokens';
25
25
  import type { TokenBinding, BindingOutput, TokenMember, TokenTupleAdmission, SelectionKey, ReboundSelection } from './token-types';
26
26
  import type { BuilderReplacementRegistration, ReplacementAdmission, ReplacedEntries, ZeroDependencyAdmission } from './replacement-types';
27
- import type { CheckDependencyCompatibility, CheckDependencyCompleteness, RegistrationEntries, Entry, EntryKeys, OverrideFactoryContext, RegistrationsFromEntries, IncrementalChecked, Introduces, IntroducesKeys, OverrideRegistrations, Overrides, ServicesOf, ReplacementKeyOf, ReplacementOutput, SelectedRegistrations, Selection, NamedAdmission, ThenableAdmission } from './types';
27
+ import type { CheckDependencyCompatibility, CheckDependencyCompleteness, RegistrationEntries, Entry, EntryKeys, ExportedServices, OverrideFactoryContext, RegistrationsFromEntries, IncrementalChecked, Introduces, IntroducesKeys, OverrideRegistrations, Overrides, ServicesOf, ReplacementKeyOf, ReplacementOutput, SelectedRegistrations, Selection, NamedAdmission, ThenableAdmission } from './types';
28
28
  type ReplacementFactory<O> = (this: void) => O;
29
29
  declare const constraintInvariant: unique symbol;
30
30
  /**
@@ -32,39 +32,71 @@ declare const constraintInvariant: unique symbol;
32
32
  *
33
33
  * Create bags through {@link DiBagApi.createBuilder} followed by {@link Builder.build} or
34
34
  * {@link Builder.buildAndStart}; the class is exported as a type and has no public constructor.
35
+ * @see https://dany-fedorov.github.io/di-bag/agent/api-card.html#bag
35
36
  */
36
37
  declare class Bag<R extends Registrations, C extends NeedConstraint = never> {
37
38
  #private;
38
- private readonly context;
39
39
  /** @internal */
40
40
  readonly [constraintInvariant]: (value: C) => C;
41
+ private readonly context;
41
42
  constructor(graph: BindingGraph, context: RuntimeContext, runtime?: BagRuntime);
42
43
  /**
43
44
  * Resolve a named or typed-token service, acquiring it lazily when needed.
44
45
  * Scoped and root services are cached according to their lifetime; transient services
45
46
  * create a new acquisition for each call. Promise-valued services keep their identity.
47
+ * An async factory's service is its Promise; nothing is awaited for you.
46
48
  * @param token - An existing public string name or typed token.
47
49
  * @returns The service exposed by the selected registration.
48
- * @throws If the bag is closing, the token is invalid, acquisition fails, or a runtime cycle is found.
50
+ * @throws `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`; `DI_BAG_INVALID_TOKEN` or `DI_BAG_MISSING_REGISTRATION` for a bad selection;
51
+ * during acquisition `DI_BAG_MISSING_DEPENDENCY`, `DI_BAG_CYCLE`, `DI_BAG_LIFETIME_DEPENDENCY`, `DI_BAG_INVALID_DEPENDENCY_ACCESS`,
52
+ * `DI_BAG_STRUCTURAL_THENABLE`, `DI_BAG_INVALID_CLASSIFIER_RESULT`, `DI_BAG_INVALID_METADATA`, `DI_BAG_PLUGIN_VALIDATION`,
53
+ * or the factory's own error.
54
+ * @example
55
+ * ```ts
56
+ * const bag = DiBag.createBuilder().register({ greeting: () => 'hello' }).build();
57
+ * const greeting: string = bag.resolve('greeting');
58
+ * ```
49
59
  */
50
60
  resolve<K extends (keyof R & string) | TokenBase>(token: K & ([K] extends [string] ? unknown : TokenMember<R, K>)): ServicesOf<R>[SelectionKey<K> & keyof R];
51
61
  /**
52
62
  * Resolve every contribution for a typed token in declaration and installation order.
53
63
  * @param token - The collection token whose contributions to acquire.
54
64
  * @returns A fresh frozen array; an unpopulated collection returns an empty array.
55
- * @throws If the bag is closing, the token is invalid, or a contribution fails.
65
+ * @throws `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`; `DI_BAG_INVALID_TOKEN` for a bad token;
66
+ * a contribution's acquisition errors as listed for {@link Bag.resolve}.
67
+ * @example
68
+ * ```ts
69
+ * const toolsKey = Symbol('tools');
70
+ * const tools = DiBag.token(toolsKey).of<string>();
71
+ * const bag = DiBag.createBuilder().contribute(tools, () => 'search').contribute(tools, () => 'fetch').build();
72
+ * const names: readonly string[] = bag.resolveAll(tools);
73
+ * ```
56
74
  */
57
75
  resolveAll<T extends TokenBase>(token: T & TokenTupleAdmission<readonly [T]> & CollectionMember<T, C>, ...invalid: [T] extends [never] ? [never] : []): ReadonlyArray<TokenService<T>>;
58
76
  /**
59
77
  * Inspect every contribution for a token without running its factories.
60
78
  * @param token - The collection token to inspect.
61
79
  * @returns Frozen snapshots in contribution order.
80
+ * @throws `DI_BAG_INVALID_TOKEN` for a bad token.
81
+ * @example
82
+ * ```ts
83
+ * const toolsKey = Symbol('tools');
84
+ * const tools = DiBag.token(toolsKey).of<string>();
85
+ * const bag = DiBag.createBuilder().contribute(tools, () => 'search').build();
86
+ * const labels = bag.inspectAll(tools).map(snapshot => snapshot.label);
87
+ * ```
62
88
  */
63
89
  inspectAll<T extends TokenBase>(token: T & TokenTupleAdmission<readonly [T]> & CollectionMember<T, C>, ...invalid: [T] extends [never] ? [never] : []): readonly RegistrationSnapshot<object, readonly unknown[]>[];
64
90
  /**
65
91
  * Inspect static metadata and copied acquisition state without resolving a service.
66
92
  * @param token - An existing public string name or typed token.
67
93
  * @returns A frozen point-in-time snapshot. Application-owned metadata payloads are not frozen.
94
+ * @throws `DI_BAG_INVALID_TOKEN` or `DI_BAG_MISSING_REGISTRATION` for a bad selection; `DI_BAG_CYCLE` for an alias cycle.
95
+ * @example
96
+ * ```ts
97
+ * const bag = DiBag.createBuilder().register({ greeting: () => 'hello' }).build();
98
+ * const acquired = bag.inspect('greeting').acquisitions.length;
99
+ * ```
68
100
  */
69
101
  inspect<K extends (keyof R & string) | TokenBase>(token: K & ([K] extends [string] ? unknown : TokenMember<R, K>)): RegistrationSnapshot<ProviderRegistrationMetadata<R[SelectionKey<K> & keyof R]>, ProviderAcquisitionMetadata<R[SelectionKey<K> & keyof R]>>;
70
102
  /**
@@ -72,12 +104,19 @@ declare class Bag<R extends Registrations, C extends NeedConstraint = never> {
72
104
  * Nothing is acquired. Named dependencies declared on factory parameters are not visible
73
105
  * until the factory runs; the static graph tool reports them from source.
74
106
  * @returns A frozen point-in-time snapshot; application-owned metadata payloads are not frozen.
107
+ * @example
108
+ * ```ts
109
+ * const bag = DiBag.createBuilder().register({ greeting: () => 'hello' }).build();
110
+ * const labels = bag.inspectGraph().bindings.map(binding => binding.label);
111
+ * ```
75
112
  */
76
113
  inspectGraph(): GraphSnapshot;
77
114
  /**
78
115
  * Create a tracked child that borrows selected parent acquisitions.
79
116
  * @param options - A checked selection of non-transient services to share lazily.
80
117
  * @returns A child owned by this bag; closing the parent closes the child first.
118
+ * @throws `DI_BAG_INVALID_SCOPE` for a malformed or transient share selection; `DI_BAG_INVALID_TOKEN` for a bad token;
119
+ * `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`.
81
120
  */
82
121
  createScope<const S extends readonly unknown[]>(options: ScopeOptions<R, S>): Bag<ScopedAliases<R, R, S>, C>;
83
122
  /**
@@ -86,35 +125,67 @@ declare class Bag<R extends Registrations, C extends NeedConstraint = never> {
86
125
  * @param overrides - Own registration properties for every selected key.
87
126
  * @param options - A disjoint selection of non-transient parent acquisitions to share.
88
127
  * @returns A child with fresh scoped acquisitions and ownership for unshared services.
89
- * @throws If the runtime selections, overrides, or sharing options are invalid.
128
+ * @throws `DI_BAG_INVALID_SCOPE` for invalid selections, overrides, or sharing; `DI_BAG_INVALID_TOKEN` or `DI_BAG_INVALID_REGISTRATION`
129
+ * for malformed input; `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`; `DI_BAG_CLASSIFIER_REQUIRED` as for {@link Builder.build}.
90
130
  */
91
- createScope<const K extends readonly unknown[], O extends OverrideFactoryContext<R, K, O>, const S extends readonly unknown[] = readonly []>(keys: K & Selection<R, K, 'createScope'>, overrides: O & object & Record<SelectionKey<K[number]>, Registration> & Overrides<R, SelectedRegistrations<K, O>> & CheckDependencyCompatibility<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckDependencyCompleteness<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CompleteConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedScopeLifetimes<NoInfer<ScopedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>, R, S>>, NoInfer<SelectedRegistrations<K, O>>, C>, options?: ScopeOptions<R, S> & DisjointScopeSelection<K, S>): Bag<ScopedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>, R, S>, C>;
131
+ createScope<const K extends readonly unknown[], O extends OverrideFactoryContext<R, K, O>, const S extends readonly unknown[] = readonly []>(keys: K & Selection<R, K, 'createScope'>, overrides: O & object & Record<SelectionKey<K[number]>, Registration> & Overrides<R, SelectedRegistrations<K, O>> & CheckDependencyCompatibility<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckDependencyCompleteness<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CompleteConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedScopeLifetimes<NoInfer<ScopedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>, R, S>>, NoInfer<SelectedRegistrations<K, O>>, WithoutExportObligations<C, SelectionKey<K[number]>>>, options?: ScopeOptions<R, S> & DisjointScopeSelection<K, S>): Bag<ScopedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>, R, S>, WithoutExportObligations<C, SelectionKey<K[number]>>>;
92
132
  /**
93
133
  * Create a tracked child with the same graph and fresh scoped acquisitions.
134
+ * Close every scope you create, typically one per request; closing the parent closes its live scopes first.
94
135
  * @returns A child that is closed before its parent finishes closing.
136
+ * @throws `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`.
137
+ * @example
138
+ * ```ts
139
+ * const app = DiBag.createBuilder().register({ requestId: () => Math.random() }).build();
140
+ * const request = app.createScope();
141
+ * const id: number = request.resolve('requestId');
142
+ * await request.close();
143
+ * ```
95
144
  */
96
145
  createScope(): Bag<UnsharedAliases<R>, C>;
97
146
  /**
98
147
  * Create an independent bag with the same graph and fresh instances.
99
148
  * @returns A new ownership family that must be closed separately.
149
+ * @throws `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`.
100
150
  */
101
151
  fork(this: Bag<R, C> & CheckedLifetimes<UnsharedAliases<R>, C>): Bag<UnsharedAliases<R>, C>;
102
152
  /**
103
- * Create an independent bag with selected replacements.
153
+ * Create an independent bag with selected replacements, the way tests substitute dependencies.
154
+ * Each override must satisfy the original contract; close the fork, since its parent does not.
104
155
  * @param keys - Existing names or tokens to replace.
105
156
  * @param overrides - Own registration properties for every selected key.
106
157
  * @returns A fresh ownership family whose graph uses the checked replacements.
107
- * @throws If a selected key is absent or lacks an own override.
158
+ * @throws `DI_BAG_INVALID_OVERRIDE` for an absent key or a missing own override; `DI_BAG_INVALID_TOKEN` or `DI_BAG_INVALID_REGISTRATION`
159
+ * for malformed input; `DI_BAG_CLOSING` or `DI_BAG_CLOSED` after `close()`; `DI_BAG_CLASSIFIER_REQUIRED` as for {@link Builder.build}.
160
+ * @example
161
+ * ```ts
162
+ * type Clock = { now(): number };
163
+ * const app = DiBag.createBuilder().register({ clock: (): Clock => ({ now: () => Date.now() }) }).build();
164
+ * const test = app.fork(['clock'], { clock: (): Clock => ({ now: () => 0 }) });
165
+ * await test.close();
166
+ * ```
108
167
  */
109
- fork<const K extends readonly unknown[], O extends OverrideFactoryContext<R, K, O>>(keys: K & Selection<R, K>, overrides: O & object & Record<SelectionKey<K[number]>, Registration> & Overrides<R, SelectedRegistrations<K, O>> & CheckDependencyCompatibility<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckDependencyCompleteness<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CompleteConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedLifetimes<UnsharedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>>, C>): Bag<UnsharedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>>, C>;
168
+ fork<const K extends readonly unknown[], O extends OverrideFactoryContext<R, K, O>>(keys: K & Selection<R, K>, overrides: O & object & Record<SelectionKey<K[number]>, Registration> & Overrides<R, SelectedRegistrations<K, O>> & CheckDependencyCompatibility<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckDependencyCompleteness<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CompleteConstraints<C, OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>> & CheckedLifetimes<UnsharedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>>, WithoutExportObligations<C, SelectionKey<K[number]>>>): Bag<UnsharedAliases<OverrideRegistrations<R, ReboundSelection<R, SelectedRegistrations<K, O>>>>, WithoutExportObligations<C, SelectionKey<K[number]>>>;
110
169
  /**
111
170
  * Close this bag, drain in-flight work, and dispose owned resources once.
112
171
  * Dependents are disposed before dependencies; remaining independent acquisitions use
113
- * reverse acquisition order. Repeated calls return the same promise.
114
- * @returns The shared shutdown promise.
115
- * @throws {@link DiBagCleanupError} when one or more disposers fail after all cleanup is attempted.
172
+ * reverse acquisition order. Without options the promise waits for cleanup however long it
173
+ * takes, and repeated calls return the same promise. With `timeoutMs` or `signal`, cleanup
174
+ * starts the same way but the returned promise stops waiting when either fires; scopes and
175
+ * forks accept the same options. Close every scope and fork you create; a parent closes its live scopes, never forks.
176
+ * @param options - An optional deadline and abort signal bounding the wait, not the cleanup.
177
+ * @returns The shared shutdown promise, or a bounded wait on it when options are given.
178
+ * @throws {@link DiBagCleanupError} (`DI_BAG_CLEANUP_FAILED`) when one or more disposers fail after all cleanup is attempted;
179
+ * `DI_BAG_CLOSE_FAILED` for other shutdown failures;
180
+ * {@link DiBagCloseCancelledError} (`DI_BAG_CLOSE_TIMEOUT` or `DI_BAG_CLOSE_ABORTED`) when the wait stops first,
181
+ * naming unfinished disposers in `details.pending`; `DI_BAG_INVALID_CLOSE` for malformed options.
182
+ * @example
183
+ * ```ts
184
+ * const bag = DiBag.createBuilder().register({ value: () => 1 }).build();
185
+ * await bag.close({ timeoutMs: 10_000, signal: AbortSignal.timeout(15_000) });
186
+ * ```
116
187
  */
117
- close(): Promise<void>;
188
+ close(options?: CloseOptions): Promise<void>;
118
189
  }
119
190
  /**
120
191
  * An immutable, type-checked graph builder. Every operation returns a new builder.
@@ -122,6 +193,7 @@ declare class Bag<R extends Registrations, C extends NeedConstraint = never> {
122
193
  * {@link Builder.build} a bag once its graph is complete, or
123
194
  * {@link Builder.buildModule} a reusable module whose unmet dependencies become
124
195
  * requirements the installing host must satisfy.
196
+ * @see https://dany-fedorov.github.io/di-bag/agent/api-card.html#builder
125
197
  */
126
198
  declare class Builder<E extends Entry, C extends NeedConstraint = never> {
127
199
  #private;
@@ -131,9 +203,17 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
131
203
  constructor(graph: BindingGraph, context: RuntimeContext);
132
204
  /**
133
205
  * Add new string-named registrations.
206
+ * A factory declares its dependencies in the type of its one object parameter; destructure it or read `deps.name`, never spread it.
134
207
  * @param more - A finite object whose own string keys are service names and values are registrations.
135
208
  * @returns A new builder containing snapshots of the supplied registrations.
136
- * @throws If the input is malformed, contains a non-string key, or duplicates a public name.
209
+ * @throws `DI_BAG_INVALID_REGISTRATION` for a malformed object or value; `DI_BAG_DUPLICATE_REGISTRATION` for a name already registered.
210
+ * @example
211
+ * ```ts
212
+ * type Clock = { now(): number };
213
+ * const builder = DiBag.createBuilder()
214
+ * .register({ clock: (): Clock => ({ now: () => Date.now() }) })
215
+ * .register({ stamp: ({ clock }: { clock: Clock }) => clock.now() });
216
+ * ```
137
217
  */
138
218
  register<N extends {
139
219
  [K in keyof N]: Registration;
@@ -143,6 +223,8 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
143
223
  * @param token - A new typed token identity.
144
224
  * @param registration - A registration whose exposed output satisfies the token service type.
145
225
  * @returns A new builder retaining the provider's metadata, lifetime, dependencies, and ownership stages.
226
+ * @throws `DI_BAG_INVALID_TOKEN` for a bad token; `DI_BAG_DUPLICATE_REGISTRATION` when it is already registered;
227
+ * `DI_BAG_INVALID_REGISTRATION` for an invalid registration.
146
228
  */
147
229
  register<T extends TokenBase, V extends Registration>(token: T & TokenTupleAdmission<readonly [T]> & IntroducesKeys<EntryKeys<E>, TokenKey<T>>, registration: V & Registration & BindingOutput<NoInfer<T>, NoInfer<V>> & ThenableAdmission<Record<TokenKey<T>, NoInfer<V>>> & IncrementalChecked<E, Record<TokenKey<T>, TokenBinding<NoInfer<T>, NoInfer<V>>>> & CheckedConstraints<C, OverrideRegistrations<RegistrationsFromEntries<E>, Record<TokenKey<T>, TokenBinding<NoInfer<T>, NoInfer<V>>>>>): Builder<E | {
148
230
  key: TokenKey<T>;
@@ -153,6 +235,12 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
153
235
  * @param destination - A new string name or typed token.
154
236
  * @param target - The existing name or token whose canonical acquisition is reused.
155
237
  * @returns A new builder; aliases add no cache or ownership of their own.
238
+ * @throws `DI_BAG_INVALID_TOKEN` for a bad token; `DI_BAG_DUPLICATE_REGISTRATION` when the destination exists;
239
+ * `DI_BAG_INVALID_ALIAS` for an absent named target.
240
+ * @example
241
+ * ```ts
242
+ * const builder = DiBag.createBuilder().register({ clock: () => Date.now() }).alias('now', 'clock');
243
+ * ```
156
244
  */
157
245
  alias<const D extends AliasSelection, const T extends AliasSelection>(destination: D & (unknown extends AliasAdmission<D> ? Introduces<RegistrationsFromEntries<E>, AliasEntries<RegistrationsFromEntries<E>, D, T>> : AliasAdmission<D>), target: T & AliasAdmission<T> & (unknown extends AliasAdmission<T> ? AliasTarget<RegistrationsFromEntries<E>, T> & AliasDestination<RegistrationsFromEntries<E>, NoInfer<D>, T> : unknown) & (unknown extends AliasAdmission<D> & AliasAdmission<T> ? IncrementalChecked<E, AliasEntries<RegistrationsFromEntries<E>, NoInfer<D>, NoInfer<T>>> & CheckedConstraints<C, OverrideRegistrations<RegistrationsFromEntries<E>, AliasEntries<RegistrationsFromEntries<E>, NoInfer<D>, NoInfer<T>>>> : unknown), ...invalid: [D] extends [never] ? [never] : [T] extends [never] ? [never] : []): Builder<E | AliasEntry<RegistrationsFromEntries<E>, D, T>, C>;
158
246
  /**
@@ -160,6 +248,13 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
160
248
  * @param token - The collection's typed token.
161
249
  * @param registration - A registration whose output satisfies the token service type.
162
250
  * @returns A new builder preserving contribution order.
251
+ * @throws `DI_BAG_INVALID_TOKEN` for a bad token; `DI_BAG_INVALID_REGISTRATION` for an invalid registration.
252
+ * @example
253
+ * ```ts
254
+ * const toolsKey = Symbol('tools');
255
+ * const tools = DiBag.token(toolsKey).of<string>();
256
+ * const builder = DiBag.createBuilder().contribute(tools, () => 'search').contribute(tools, () => 'fetch');
257
+ * ```
163
258
  */
164
259
  readonly contribute: BuilderContribute<E, C>;
165
260
  /**
@@ -168,24 +263,39 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
168
263
  * @param registration - The replacement, checked against every surviving consumer.
169
264
  * @returns A new builder with the replacement.
170
265
  * @typeParam V - The exact replacement factory or disposable-factory type.
266
+ * @throws `DI_BAG_INVALID_REPLACEMENT` for an absent key; `DI_BAG_INVALID_REGISTRATION` for an invalid registration.
267
+ * @example
268
+ * ```ts
269
+ * const builder = DiBag.createBuilder().register({ clock: () => Date.now() }).replace('clock', () => 0);
270
+ * ```
171
271
  */
172
272
  replace<const K extends string, V extends (ReplacementFactory<ReplacementOutput<NoInfer<RegistrationsFromEntries<E>>, K, C>>) | FactoryWithDisposal<ReplacementFactory<ReplacementOutput<NoInfer<RegistrationsFromEntries<E>>, K, C>>>>(key: K & ReplacementKeyOf<EntryKeys<E>, K>, registration: V & (Factory | FactoryWithDisposal<Factory>) & ZeroDependencyAdmission<NoInfer<V>> & CheckedConstraints<C, OverrideRegistrations<RegistrationsFromEntries<E>, Record<K, NoInfer<V>>>>): Builder<Exclude<E, {
173
273
  key: K;
174
274
  }> | {
175
275
  key: K;
176
276
  registration: V;
177
- }, C>;
277
+ }, WithoutExportObligations<C, K>>;
178
278
  /**
179
279
  * Replace an existing named or typed-token registration.
180
280
  * @param key - The single existing name or token to replace.
181
281
  * @param registration - A replacement compatible with the token and known consumers.
182
282
  * @returns A new builder with the replacement and its inferred service type.
283
+ * @throws `DI_BAG_INVALID_REPLACEMENT` for an absent key; `DI_BAG_INVALID_TOKEN` or `DI_BAG_INVALID_REGISTRATION` for malformed input.
183
284
  */
184
- replace<const K extends string | TokenBase, V extends Registration>(key: K & NoInfer<ReplacementAdmission<RegistrationsFromEntries<E>, K>>, registration: V & Registration & BuilderReplacementRegistration<E, C, NoInfer<K>, V>): Builder<ReplacedEntries<E, K, V>, C>;
285
+ replace<const K extends string | TokenBase, V extends Registration>(key: K & NoInfer<ReplacementAdmission<RegistrationsFromEntries<E>, K>>, registration: V & Registration & BuilderReplacementRegistration<E, C, NoInfer<K>, V>): Builder<ReplacedEntries<E, K, V>, WithoutExportObligations<C, SelectionKey<K>>>;
185
286
  /**
186
287
  * Install a sealed module, allocating fresh private bindings for this installation.
288
+ * The installing host must register every requirement the module does not register itself.
187
289
  * @param module - A module whose public names do not collide and whose external requirements remain checkable.
188
290
  * @returns A new builder exposing only the module's selected exports.
291
+ * @throws `DI_BAG_INVALID_MODULE` for a value not made by `buildModule`; `DI_BAG_DUPLICATE_REGISTRATION` when an export name is already registered.
292
+ * @example
293
+ * ```ts
294
+ * const greeting = DiBag.createBuilder()
295
+ * .register({ greet: ({ name }: { name: string }) => `hello, ${name}` })
296
+ * .buildModule(['greet']);
297
+ * const bag = DiBag.createBuilder().installModule(greeting).register({ name: () => 'Ada' }).build();
298
+ * ```
189
299
  */
190
300
  installModule<P extends object, R extends object, MC extends NeedConstraint, D extends Registrations>(module: Module<P, R, MC, D> & IntroducesKeys<EntryKeys<E>, keyof D> & IncrementalChecked<E, D> & IncrementalConstraints<C, MC, RegistrationsFromEntries<E>, D>): Builder<E | RegistrationEntries<D>, C | MC>;
191
301
  /**
@@ -193,6 +303,11 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
193
303
  * Write `builder.verifyGraph() satisfies void;` so a rejected graph fails on that line with
194
304
  * the complete message and details, instead of at the start of the builder expression.
195
305
  * @returns `void` for a buildable graph; otherwise the failure that `build()` would report.
306
+ * @example
307
+ * ```ts
308
+ * const builder = DiBag.createBuilder().register({ greeting: () => 'hello' });
309
+ * builder.verifyGraph() satisfies void;
310
+ * ```
196
311
  */
197
312
  verifyGraph<Self extends Builder<E, C>>(this: Self): CompositionReport<Self>;
198
313
  /**
@@ -201,14 +316,33 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
201
316
  * become requirements of the module. Installed modules nest: their private
202
317
  * bindings and retained constraints are re-scoped inside this module.
203
318
  * @param keys - A finite tuple of existing names or tokens; an empty tuple is allowed.
319
+ * @param options - An optional `label`; each installation names its private bindings `<label>/<key>` in
320
+ * error messages, cycle paths, `inspectGraph()`, and observer events, and nested labels compose as `outer/inner/key`.
204
321
  * @returns An immutable module that can be renamed or installed in another builder.
205
- * @throws If the selection is not a tuple or contains an absent name or token.
322
+ * @throws `DI_BAG_INVALID_EXPORT` if the selection is not a tuple, contains an absent name or token, or the label is not a non-empty string;
323
+ * `DI_BAG_INVALID_TOKEN` for a value that is not a genuine token.
324
+ * @example
325
+ * ```ts
326
+ * const orders = DiBag.createBuilder()
327
+ * .register({ repository: () => new Map<string, number>() })
328
+ * .register({ placeOrder: ({ repository }: { repository: Map<string, number> }) => (id: string) => repository.set(id, 1) })
329
+ * .buildModule(['placeOrder'], { label: 'orders' });
330
+ * // Errors and inspectGraph() name the private binding 'orders/repository'.
331
+ * const app = DiBag.createBuilder().installModule(orders).build();
332
+ * ```
206
333
  */
207
- buildModule<const K extends readonly unknown[]>(keys: K & Selection<RegistrationsFromEntries<E>, K, 'buildModule'>): Module<Pick<ServicesOf<RegistrationsFromEntries<E>>, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>, ExternalRequirements<ModuleSealedConstraints<E, C, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>>, ModuleSealedConstraints<E, C, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>, ModulePublicProviders<RegistrationsFromEntries<E>, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>>;
334
+ buildModule<const K extends readonly unknown[]>(keys: K & Selection<RegistrationsFromEntries<E>, K, 'buildModule'> & SealAdmission<RegistrationsFromEntries<E>, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>, C>, options?: ModuleOptions): Module<ExportedServices<ServicesOf<RegistrationsFromEntries<E>>, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>, ExternalRequirements<ModuleSealedConstraints<E, C, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>>, ModuleSealedConstraints<E, C, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>, ModulePublicProviders<RegistrationsFromEntries<E>, Extract<SelectionKey<K[number]>, keyof RegistrationsFromEntries<E>>>>;
208
335
  /**
209
336
  * Finish a complete graph as a lazy bag.
337
+ * The bag owns what it acquires; close it when done.
210
338
  * @returns A fresh bag that owns the acquisitions it creates.
211
- * @throws At runtime if automatic acquisition is used without a configured Promise classifier.
339
+ * @throws `DI_BAG_CLASSIFIER_REQUIRED` when a registration uses `auto` acquisition, the facade has no Promise
340
+ * classifier, and the host has no `process.getBuiltinModule`.
341
+ * @example
342
+ * ```ts
343
+ * const bag = DiBag.createBuilder().register({ greeting: () => 'hello' }).build();
344
+ * await bag.close();
345
+ * ```
212
346
  */
213
347
  build(this: Builder<E, C> & CheckDependencyCompleteness<RegistrationsFromEntries<E>> & CompleteConstraints<C, RegistrationsFromEntries<E>> & CheckedLifetimes<RegistrationsFromEntries<E>, C>): Bag<RegistrationsFromEntries<E>, C>;
214
348
  /**
@@ -216,47 +350,192 @@ declare class Builder<E extends Entry, C extends NeedConstraint = never> {
216
350
  * @param keys - A finite tuple of existing names or typed tokens to make ready.
217
351
  * @param options - Optional cancellation signal, positive timeout, and parallel, sequential, or positive safe integer bounded scheduling.
218
352
  * @returns A promise for the new bag after every selected final stage is ready.
219
- * @throws {@link DiBagStartupError} after rollback on acquisition failure, or
220
- * {@link DiBagStartupCancelledError} promptly on abort or timeout.
353
+ * @throws {@link DiBagStartupError} (`DI_BAG_STARTUP_FAILED`) after rollback on acquisition failure;
354
+ * {@link DiBagStartupCancelledError} (`DI_BAG_STARTUP_CANCELLED`) promptly on abort or timeout;
355
+ * `DI_BAG_INVALID_STARTUP` for malformed keys or options; `DI_BAG_INVALID_TOKEN` for a bad token;
356
+ * `DI_BAG_CLASSIFIER_REQUIRED` as for {@link Builder.build}. Each arrives as a rejection.
357
+ * @example
358
+ * ```ts
359
+ * const bag = await DiBag.createBuilder()
360
+ * .register({ db: async () => ({ ping: () => true }) })
361
+ * .buildAndStart(['db'], { timeoutMs: 5_000 });
362
+ * ```
221
363
  */
222
364
  buildAndStart<const K extends readonly unknown[]>(this: Builder<E, C> & CheckDependencyCompleteness<RegistrationsFromEntries<E>> & CompleteConstraints<C, RegistrationsFromEntries<E>> & CheckedLifetimes<RegistrationsFromEntries<E>, C>, keys: K & Selection<RegistrationsFromEntries<E>, K, 'buildAndStart'>, options?: StartupOptions): Promise<Bag<RegistrationsFromEntries<E>, C>>;
223
365
  }
224
366
  export type { Bag, Builder };
225
- /** Immutable facade configuration. Observers append in the supplied order. */
367
+ /**
368
+ * Immutable facade configuration. Observers append in the supplied order.
369
+ * @see https://dany-fedorov.github.io/di-bag/guides/tutorial.html#observe-lifecycle-transitions
370
+ */
226
371
  export interface ConfigurationOptions {
227
372
  readonly runtime?: RuntimeOptions;
228
373
  readonly observers?: readonly ObserverOptions[];
229
374
  }
230
- /** The immutable public entry surface used by {@link DiBag} and derived facades. */
375
+ /**
376
+ * The immutable public entry surface used by {@link DiBag} and derived facades.
377
+ * @see https://dany-fedorov.github.io/di-bag/agent/api-card.html#dibag-facade
378
+ */
231
379
  export interface DiBagApi {
232
- /** Return a facade with inherited runtime settings and appended observers. */
380
+ /**
381
+ * Return a facade with inherited runtime settings and appended observers.
382
+ * @throws `DI_BAG_INVALID_CONFIGURATION` for a non-object, a runtime without `isNativePromise`, or malformed observers.
383
+ * @example
384
+ * ```ts
385
+ * const Observed = DiBag.withConfiguration({
386
+ * observers: [{ onEvent: event => console.log(event.kind), onError: failure => console.error(failure.error) }],
387
+ * });
388
+ * ```
389
+ */
233
390
  withConfiguration: (options: ConfigurationOptions) => DiBagApi;
234
- /** Describe a named-dependency factory, optionally receiving acquisition context. */
391
+ /**
392
+ * Describe a named-dependency factory with an explicit acquisition mode or the acquisition's abort signal.
393
+ * A factory that returns a non-Promise object with a `then` method needs `acquisitionMode: 'raw'` or must return `Promise.resolve(value)`.
394
+ * @throws `DI_BAG_INVALID_FACTORY` for a non-function or an unknown `context`; `DI_BAG_INVALID_ACQUISITION_MODE` for an unknown mode.
395
+ * @example
396
+ * ```ts
397
+ * type Query = { then(done: (rows: string[]) => void): void };
398
+ * const query = DiBag.fromFactory((): Query => ({ then: done => done([]) }), { acquisitionMode: 'raw' });
399
+ * ```
400
+ */
235
401
  fromFactory: typeof fromFactory;
236
- /** Create a nominal typed token with a diagnostic label. */
402
+ /**
403
+ * Create a typed token from a unique symbol; `.of<Service>()` fixes its service type.
404
+ * @throws `DI_BAG_INVALID_TOKEN` when the key is not a symbol.
405
+ * @example
406
+ * ```ts
407
+ * const clockKey = Symbol('clock');
408
+ * const clock = DiBag.token(clockKey).of<{ now(): number }>();
409
+ * ```
410
+ */
237
411
  token: typeof token;
238
- /** Create a positional dependency that yields undefined only when unregistered. */
412
+ /**
413
+ * Create a positional dependency that yields `undefined` only when the token is unregistered.
414
+ * @throws `DI_BAG_INVALID_TOKEN` for a value that is not a genuine token.
415
+ * @example
416
+ * ```ts
417
+ * const clockKey = Symbol('clock');
418
+ * const clock = DiBag.token(clockKey).of<{ now(): number }>();
419
+ * const stamp = DiBag.fromFunction([DiBag.optional(clock)], source => source?.now() ?? 0);
420
+ * ```
421
+ */
239
422
  optional: typeof optional;
240
- /** Create a positional dependency resolved on demand by the receiving service. */
423
+ /**
424
+ * Create a positional dependency supplied as a function that resolves the token when called.
425
+ * @throws `DI_BAG_INVALID_TOKEN` for a value that is not a genuine token.
426
+ * @example
427
+ * ```ts
428
+ * const clockKey = Symbol('clock');
429
+ * const clock = DiBag.token(clockKey).of<{ now(): number }>();
430
+ * const stamp = DiBag.fromFunction([DiBag.lazy(clock)], getClock => () => getClock().now());
431
+ * ```
432
+ */
241
433
  lazy: typeof lazy;
242
- /** Create a positional dependency containing ordered collection contributions. */
434
+ /**
435
+ * Create a positional dependency containing every contribution to a collection token, in order.
436
+ * @throws `DI_BAG_INVALID_TOKEN` for a value that is not a genuine token.
437
+ * @example
438
+ * ```ts
439
+ * const toolsKey = Symbol('tools');
440
+ * const tools = DiBag.token(toolsKey).of<string>();
441
+ * const menu = DiBag.fromFunction([DiBag.all(tools)], names => names.join(', '));
442
+ * ```
443
+ */
243
444
  all: typeof all;
244
- /** Validate an unknown plugin descriptor and its acquired output at a checked boundary. */
445
+ /**
446
+ * Validate an unknown plugin descriptor now and its acquired output at acquisition.
447
+ * @throws `DI_BAG_INVALID_TOKEN` for a malformed dependency tuple; `DI_BAG_INVALID_PLUGIN_OPTIONS` for malformed options;
448
+ * {@link DiBagPluginValidationError} (`DI_BAG_PLUGIN_VALIDATION`) for an invalid descriptor, or at acquisition for rejected output.
449
+ * @example
450
+ * ```ts
451
+ * declare const descriptor: unknown;
452
+ * const greeter = DiBag.fromPlugin([], descriptor, {
453
+ * acquisitionMode: 'raw',
454
+ * validate: (value): value is () => string => typeof value === 'function',
455
+ * });
456
+ * ```
457
+ */
245
458
  fromPlugin: PluginProviderFactory;
246
- /** Adapt a positional function with strict dependency tuple and argument checking. */
459
+ /**
460
+ * Adapt a positional function whose parameters receive the listed tokens' services.
461
+ * @throws `DI_BAG_INVALID_TOKEN` for a malformed token tuple; `DI_BAG_INVALID_FUNCTION` for a non-function;
462
+ * `DI_BAG_INVALID_ACQUISITION_MODE` for an unknown mode.
463
+ * @example
464
+ * ```ts
465
+ * const clockKey = Symbol('clock');
466
+ * const clock = DiBag.token(clockKey).of<{ now(): number }>();
467
+ * const stamp = DiBag.fromFunction([clock], source => new Date(source.now()).toISOString());
468
+ * ```
469
+ */
247
470
  fromFunction: typeof fromFunction;
248
- /** Adapt a concrete constructor with positional dependency injection. */
471
+ /**
472
+ * Adapt a class whose constructor parameters receive the listed tokens' services.
473
+ * @throws `DI_BAG_INVALID_TOKEN` for a malformed token tuple; `DI_BAG_INVALID_CONSTRUCTOR` for a non-constructable value;
474
+ * `DI_BAG_INVALID_ACQUISITION_MODE` for an unknown mode.
475
+ * @example
476
+ * ```ts
477
+ * class Greeter { constructor(readonly greeting: string) {} }
478
+ * const greetingKey = Symbol('greeting');
479
+ * const greeter = DiBag.fromClass([DiBag.token(greetingKey).of<string>()], Greeter);
480
+ * ```
481
+ */
249
482
  fromClass: typeof fromClass;
250
- /** Begin an empty immutable graph; build creates its owning bag, buildModule seals a reusable module. */
483
+ /**
484
+ * Begin an empty immutable graph; `build` creates its owning bag, `buildModule` seals a reusable module.
485
+ * @example
486
+ * ```ts
487
+ * const bag = DiBag.createBuilder().register({ greeting: () => 'hello' }).build();
488
+ * ```
489
+ */
251
490
  createBuilder: () => Builder<never>;
252
- /** Attach owned-value cleanup while retaining earlier disposal stages. */
491
+ /**
492
+ * Make the bag own a factory's value and run `dispose` on it when the bag closes.
493
+ * `close()` runs disposers, dependents first; close every scope and fork you create.
494
+ * @throws `DI_BAG_INVALID_REGISTRATION` when the registration is neither a function nor a provider.
495
+ * @example
496
+ * ```ts
497
+ * const bag = DiBag.createBuilder()
498
+ * .register({ controller: DiBag.withDisposal(() => new AbortController(), controller => controller.abort()) })
499
+ * .build();
500
+ * await bag.close();
501
+ * ```
502
+ */
253
503
  withDisposal: typeof withDisposal;
254
- /** Select root, scoped, or transient caching within an ownership family. */
504
+ /**
505
+ * Select `root`, `scoped` (the default), or `transient` caching for a registration.
506
+ * Mark a shared client `root` only when nothing it depends on is scoped.
507
+ * @throws `DI_BAG_INVALID_LIFETIME` for an unknown lifetime or malformed options; `DI_BAG_INVALID_REGISTRATION` for an invalid registration.
508
+ * @example
509
+ * ```ts
510
+ * const bag = DiBag.createBuilder()
511
+ * .register({ cache: DiBag.withLifetime(() => new Map<string, string>(), 'root') })
512
+ * .build();
513
+ * ```
514
+ */
255
515
  withLifetime: typeof withLifetime;
256
- /** Attach registration metadata and ordered acquisition metadata in direct or awaited mode. */
516
+ /**
517
+ * Attach static registration metadata, or per-acquisition metadata in direct or awaited mode.
518
+ * @throws `DI_BAG_INVALID_METADATA` for malformed options or, at acquisition, a describe result that is not a plain record;
519
+ * `DI_BAG_DUPLICATE_METADATA` for a repeated key; `DI_BAG_INVALID_REGISTRATION` for an invalid registration.
520
+ * @example
521
+ * ```ts
522
+ * const greeting = DiBag.withMetadata(() => 'hello', { static: { owner: 'greeting' } });
523
+ * ```
524
+ */
257
525
  withMetadata: typeof withMetadata;
258
- /** Transform the exposed service while retaining dependencies, metadata, lifetime, and existing ownership. */
526
+ /**
527
+ * Transform the exposed service while retaining dependencies, metadata, lifetime, and existing ownership.
528
+ * @throws `DI_BAG_INVALID_TRANSFORM` for a bad mode or callback; `DI_BAG_INVALID_ACQUISITION_MODE` for an unknown mode;
529
+ * `DI_BAG_INVALID_REGISTRATION` for an invalid registration.
530
+ * @example
531
+ * ```ts
532
+ * const shout = DiBag.transformService(() => 'hello', { mode: 'direct', transform: text => text.toUpperCase() });
533
+ * ```
534
+ */
259
535
  transformService: typeof transformService;
260
536
  }
261
- /** The portable, immutable DI Bag facade. Configure `auto` acquisition or use explicit modes. */
537
+ /**
538
+ * The immutable DI Bag facade. `auto` acquisition uses the host classifier where `process.getBuiltinModule`
539
+ * exists; elsewhere configure one or use explicit modes.
540
+ */
262
541
  export declare const DiBag: DiBagApi;