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.
- package/AGENTS.md +149 -0
- package/README.md +59 -46
- package/dist/acquisition-context.d.ts +8 -2
- package/dist/acquisition-mode.d.ts +9 -4
- package/dist/acquisition-mode.js +25 -7
- package/dist/acquisition.d.ts +2 -0
- package/dist/acquisition.js +9 -0
- package/dist/alias-types.d.ts +12 -3
- package/dist/composition-report.d.ts +3 -2
- package/dist/composition.d.ts +8 -2
- package/dist/contribution-types.d.ts +26 -18
- package/dist/dependency-references.d.ts +16 -4
- package/dist/di-bag.d.ts +320 -41
- package/dist/di-bag.js +86 -14
- package/dist/errors.d.ts +115 -8
- package/dist/errors.js +113 -12
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -1
- package/dist/inspection.d.ts +21 -5
- package/dist/lifetime-types.d.ts +281 -180
- package/dist/lifetime.d.ts +4 -1
- package/dist/module-types.d.ts +87 -30
- package/dist/module.d.ts +18 -4
- package/dist/module.js +31 -7
- package/dist/observers.d.ts +25 -6
- package/dist/plugins.d.ts +17 -4
- package/dist/provider.d.ts +41 -10
- package/dist/provider.js +1 -0
- package/dist/registration.d.ts +8 -2
- package/dist/registration.js +4 -1
- package/dist/runtime.d.ts +12 -3
- package/dist/runtime.js +25 -8
- package/dist/scope-types.d.ts +20 -5
- package/dist/startup.d.ts +19 -1
- package/dist/startup.js +72 -11
- package/dist/token-types.d.ts +26 -8
- package/dist/tokens.d.ts +10 -2
- package/dist/tokens.js +2 -0
- package/dist/types.d.ts +68 -22
- package/docs/agent/api-card.md +337 -0
- package/docs/agent/errors.md +1042 -0
- package/docs/agent/recipes.md +290 -0
- 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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
114
|
-
*
|
|
115
|
-
*
|
|
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
|
|
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
|
|
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<
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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;
|