@codefast/di 0.8.0 → 0.8.1
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/CHANGELOG.md +13 -0
- package/README.md +242 -159
- package/dist/ambient/active-container.d.ts +1 -2
- package/dist/ambient/active-container.js +1 -2
- package/dist/container/binding-builders.d.ts +1 -2
- package/dist/container/binding-builders.js +1 -2
- package/dist/container/container.d.ts +1 -2
- package/dist/container/container.js +1 -2
- package/dist/core/binding-scope.d.ts +1 -2
- package/dist/core/binding-scope.js +1 -2
- package/dist/core/binding.d.ts +1 -2
- package/dist/core/binding.js +1 -2
- package/dist/core/constraint-requirement.d.ts +1 -2
- package/dist/core/constraint-requirement.js +1 -2
- package/dist/core/constructor-type.d.ts +1 -2
- package/dist/core/constructor-type.js +1 -2
- package/dist/core/map-upsert.d.ts +1 -2
- package/dist/core/map-upsert.js +1 -2
- package/dist/core/module.d.ts +1 -2
- package/dist/core/module.js +1 -2
- package/dist/core/registry.d.ts +1 -2
- package/dist/core/registry.js +1 -2
- package/dist/core/tag.d.ts +1 -2
- package/dist/core/tag.js +1 -2
- package/dist/core/token.d.ts +1 -2
- package/dist/core/token.js +1 -2
- package/dist/core/types.d.ts +1 -2
- package/dist/core/types.js +1 -2
- package/dist/decorators/inject.d.ts +1 -2
- package/dist/decorators/inject.js +1 -2
- package/dist/decorators/injectable.d.ts +1 -2
- package/dist/decorators/injectable.js +1 -2
- package/dist/decorators/lifecycle-decorators.d.ts +1 -2
- package/dist/decorators/lifecycle-decorators.js +1 -2
- package/dist/errors/diagnostics.d.ts +1 -2
- package/dist/errors/diagnostics.js +1 -2
- package/dist/errors/errors.d.ts +1 -2
- package/dist/errors/errors.js +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/injection/descriptor.d.ts +1 -2
- package/dist/injection/descriptor.js +1 -2
- package/dist/injection/resolve-options.d.ts +1 -2
- package/dist/injection/resolve-options.js +1 -2
- package/dist/introspection/dependency-graph.d.ts +1 -2
- package/dist/introspection/dependency-graph.js +1 -2
- package/dist/introspection/graph-adapters/cytoscape.d.ts +1 -2
- package/dist/introspection/graph-adapters/cytoscape.js +1 -2
- package/dist/introspection/graph-adapters/dot.d.ts +1 -2
- package/dist/introspection/graph-adapters/dot.js +1 -2
- package/dist/introspection/graph-adapters/mermaid.d.ts +1 -2
- package/dist/introspection/graph-adapters/mermaid.js +1 -2
- package/dist/introspection/graph-adapters/reactflow.d.ts +1 -2
- package/dist/introspection/graph-adapters/reactflow.js +1 -2
- package/dist/introspection/inspector.d.ts +1 -2
- package/dist/introspection/inspector.js +1 -2
- package/dist/lifecycle/lifecycle-manager.d.ts +1 -2
- package/dist/lifecycle/lifecycle-manager.js +1 -2
- package/dist/lifecycle/scope-manager.d.ts +1 -2
- package/dist/lifecycle/scope-manager.js +1 -2
- package/dist/metadata/metadata-keys.d.ts +1 -2
- package/dist/metadata/metadata-keys.js +1 -2
- package/dist/metadata/metadata-reader-token.d.ts +1 -2
- package/dist/metadata/metadata-reader-token.js +1 -2
- package/dist/metadata/metadata-types.d.ts +1 -2
- package/dist/metadata/metadata-types.js +1 -2
- package/dist/metadata/symbol-metadata-reader.d.ts +1 -2
- package/dist/metadata/symbol-metadata-reader.js +1 -2
- package/dist/metadata/verifying-metadata-reader.d.ts +1 -2
- package/dist/metadata/verifying-metadata-reader.js +1 -2
- package/dist/resolution/cache/activation-need.d.ts +1 -2
- package/dist/resolution/cache/activation-need.js +1 -2
- package/dist/resolution/cache/binding-lookup-cache.d.ts +1 -2
- package/dist/resolution/cache/binding-lookup-cache.js +1 -2
- package/dist/resolution/cache/class-introspector.d.ts +1 -2
- package/dist/resolution/cache/class-introspector.js +1 -2
- package/dist/resolution/context.d.ts +1 -2
- package/dist/resolution/context.js +1 -2
- package/dist/resolution/path/resolution-path.d.ts +1 -2
- package/dist/resolution/path/resolution-path.js +1 -2
- package/dist/resolution/plan/instantiation-plan.d.ts +1 -2
- package/dist/resolution/plan/instantiation-plan.js +1 -2
- package/dist/resolution/resolver.d.ts +1 -2
- package/dist/resolution/resolver.js +1 -2
- package/dist/resolution/select/binding-select.d.ts +1 -2
- package/dist/resolution/select/binding-select.js +1 -2
- package/dist/resolution/select/constraints.d.ts +1 -2
- package/dist/resolution/select/constraints.js +1 -2
- package/package.json +6 -58
- package/dist/ambient/active-container.d.ts.map +0 -1
- package/dist/ambient/active-container.js.map +0 -1
- package/dist/container/binding-builders.d.ts.map +0 -1
- package/dist/container/binding-builders.js.map +0 -1
- package/dist/container/container.d.ts.map +0 -1
- package/dist/container/container.js.map +0 -1
- package/dist/core/binding-scope.d.ts.map +0 -1
- package/dist/core/binding-scope.js.map +0 -1
- package/dist/core/binding.d.ts.map +0 -1
- package/dist/core/binding.js.map +0 -1
- package/dist/core/constraint-requirement.d.ts.map +0 -1
- package/dist/core/constraint-requirement.js.map +0 -1
- package/dist/core/constructor-type.d.ts.map +0 -1
- package/dist/core/constructor-type.js.map +0 -1
- package/dist/core/map-upsert.d.ts.map +0 -1
- package/dist/core/map-upsert.js.map +0 -1
- package/dist/core/module.d.ts.map +0 -1
- package/dist/core/module.js.map +0 -1
- package/dist/core/registry.d.ts.map +0 -1
- package/dist/core/registry.js.map +0 -1
- package/dist/core/tag.d.ts.map +0 -1
- package/dist/core/tag.js.map +0 -1
- package/dist/core/token.d.ts.map +0 -1
- package/dist/core/token.js.map +0 -1
- package/dist/core/types.d.ts.map +0 -1
- package/dist/core/types.js.map +0 -1
- package/dist/decorators/inject.d.ts.map +0 -1
- package/dist/decorators/inject.js.map +0 -1
- package/dist/decorators/injectable.d.ts.map +0 -1
- package/dist/decorators/injectable.js.map +0 -1
- package/dist/decorators/lifecycle-decorators.d.ts.map +0 -1
- package/dist/decorators/lifecycle-decorators.js.map +0 -1
- package/dist/errors/diagnostics.d.ts.map +0 -1
- package/dist/errors/diagnostics.js.map +0 -1
- package/dist/errors/errors.d.ts.map +0 -1
- package/dist/errors/errors.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/injection/descriptor.d.ts.map +0 -1
- package/dist/injection/descriptor.js.map +0 -1
- package/dist/injection/resolve-options.d.ts.map +0 -1
- package/dist/injection/resolve-options.js.map +0 -1
- package/dist/introspection/dependency-graph.d.ts.map +0 -1
- package/dist/introspection/dependency-graph.js.map +0 -1
- package/dist/introspection/graph-adapters/cytoscape.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/cytoscape.js.map +0 -1
- package/dist/introspection/graph-adapters/dot.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/dot.js.map +0 -1
- package/dist/introspection/graph-adapters/mermaid.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/mermaid.js.map +0 -1
- package/dist/introspection/graph-adapters/reactflow.d.ts.map +0 -1
- package/dist/introspection/graph-adapters/reactflow.js.map +0 -1
- package/dist/introspection/inspector.d.ts.map +0 -1
- package/dist/introspection/inspector.js.map +0 -1
- package/dist/lifecycle/lifecycle-manager.d.ts.map +0 -1
- package/dist/lifecycle/lifecycle-manager.js.map +0 -1
- package/dist/lifecycle/scope-manager.d.ts.map +0 -1
- package/dist/lifecycle/scope-manager.js.map +0 -1
- package/dist/metadata/metadata-keys.d.ts.map +0 -1
- package/dist/metadata/metadata-keys.js.map +0 -1
- package/dist/metadata/metadata-reader-token.d.ts.map +0 -1
- package/dist/metadata/metadata-reader-token.js.map +0 -1
- package/dist/metadata/metadata-types.d.ts.map +0 -1
- package/dist/metadata/metadata-types.js.map +0 -1
- package/dist/metadata/symbol-metadata-reader.d.ts.map +0 -1
- package/dist/metadata/symbol-metadata-reader.js.map +0 -1
- package/dist/metadata/verifying-metadata-reader.d.ts.map +0 -1
- package/dist/metadata/verifying-metadata-reader.js.map +0 -1
- package/dist/resolution/cache/activation-need.d.ts.map +0 -1
- package/dist/resolution/cache/activation-need.js.map +0 -1
- package/dist/resolution/cache/binding-lookup-cache.d.ts.map +0 -1
- package/dist/resolution/cache/binding-lookup-cache.js.map +0 -1
- package/dist/resolution/cache/class-introspector.d.ts.map +0 -1
- package/dist/resolution/cache/class-introspector.js.map +0 -1
- package/dist/resolution/context.d.ts.map +0 -1
- package/dist/resolution/context.js.map +0 -1
- package/dist/resolution/path/resolution-path.d.ts.map +0 -1
- package/dist/resolution/path/resolution-path.js.map +0 -1
- package/dist/resolution/plan/instantiation-plan.d.ts.map +0 -1
- package/dist/resolution/plan/instantiation-plan.js.map +0 -1
- package/dist/resolution/resolver.d.ts.map +0 -1
- package/dist/resolution/resolver.js.map +0 -1
- package/dist/resolution/select/binding-select.d.ts.map +0 -1
- package/dist/resolution/select/binding-select.js.map +0 -1
- package/dist/resolution/select/constraints.d.ts.map +0 -1
- package/dist/resolution/select/constraints.js.map +0 -1
- package/src/ambient/active-container.ts +0 -69
- package/src/container/binding-builders.ts +0 -337
- package/src/container/container.ts +0 -972
- package/src/core/binding-scope.ts +0 -15
- package/src/core/binding.ts +0 -505
- package/src/core/constraint-requirement.ts +0 -94
- package/src/core/constructor-type.ts +0 -18
- package/src/core/map-upsert.ts +0 -53
- package/src/core/module.ts +0 -117
- package/src/core/registry.ts +0 -319
- package/src/core/tag.ts +0 -212
- package/src/core/token.ts +0 -31
- package/src/core/types.ts +0 -149
- package/src/decorators/inject.ts +0 -101
- package/src/decorators/injectable.ts +0 -134
- package/src/decorators/lifecycle-decorators.ts +0 -43
- package/src/errors/diagnostics.ts +0 -45
- package/src/errors/errors.ts +0 -499
- package/src/index.ts +0 -139
- package/src/injection/descriptor.ts +0 -218
- package/src/injection/resolve-options.ts +0 -201
- package/src/introspection/dependency-graph.ts +0 -296
- package/src/introspection/graph-adapters/cytoscape.ts +0 -78
- package/src/introspection/graph-adapters/dot.ts +0 -32
- package/src/introspection/graph-adapters/mermaid.ts +0 -61
- package/src/introspection/graph-adapters/reactflow.ts +0 -84
- package/src/introspection/inspector.ts +0 -134
- package/src/lifecycle/lifecycle-manager.ts +0 -272
- package/src/lifecycle/scope-manager.ts +0 -158
- package/src/metadata/metadata-keys.ts +0 -28
- package/src/metadata/metadata-reader-token.ts +0 -10
- package/src/metadata/metadata-types.ts +0 -57
- package/src/metadata/symbol-metadata-reader.ts +0 -126
- package/src/metadata/verifying-metadata-reader.ts +0 -41
- package/src/resolution/cache/activation-need.ts +0 -87
- package/src/resolution/cache/binding-lookup-cache.ts +0 -169
- package/src/resolution/cache/class-introspector.ts +0 -256
- package/src/resolution/context.ts +0 -331
- package/src/resolution/path/resolution-path.ts +0 -167
- package/src/resolution/plan/instantiation-plan.ts +0 -592
- package/src/resolution/resolver.ts +0 -1654
- package/src/resolution/select/binding-select.ts +0 -207
- package/src/resolution/select/constraints.ts +0 -146
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @codefast/di
|
|
2
2
|
|
|
3
|
+
## 0.8.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#791](https://github.com/codefastlabs/codefast/pull/791) [`37a212b`](https://github.com/codefastlabs/codefast/commit/37a212b4d805588413159e11e872b98db82326bf) Thanks [@thevuong](https://github.com/thevuong)! - Point the README's license badge and "License" section at the package's own `LICENSE` file instead of the monorepo root.
|
|
8
|
+
|
|
9
|
+
- [#796](https://github.com/codefastlabs/codefast/pull/796) [`ba04d27`](https://github.com/codefastlabs/codefast/commit/ba04d2703c59a1677f52e6a9fffd0ec202328218) Thanks [@thevuong](https://github.com/thevuong)! - Rewrite the README around one structure — what the package is, installation and requirements, a complete quick start,
|
|
10
|
+
the concepts in learning order, then the documents and the license — with every API claim checked against the current
|
|
11
|
+
code and no figures that go stale.
|
|
12
|
+
|
|
13
|
+
- [#784](https://github.com/codefastlabs/codefast/pull/784) [`ad2f93a`](https://github.com/codefastlabs/codefast/commit/ad2f93a688e99c3ed8be6ceeae9d6cdd6be861bc) Thanks [@thevuong](https://github.com/thevuong)! - Ship the MIT `LICENSE` file in the published package. `files` already listed it, but the file was missing from the
|
|
14
|
+
package directory, so the tarball had none.
|
|
15
|
+
|
|
3
16
|
## 0.8.0
|
|
4
17
|
|
|
5
18
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -1,41 +1,47 @@
|
|
|
1
1
|
# @codefast/di
|
|
2
2
|
|
|
3
|
-
Lightweight, type-safe dependency injection for
|
|
3
|
+
Lightweight, type-safe dependency injection for TypeScript applications, built on TC39 Stage 3 decorators with no
|
|
4
4
|
`reflect-metadata` and no `experimentalDecorators`.
|
|
5
5
|
|
|
6
6
|
[](https://www.npmjs.com/package/@codefast/di)
|
|
7
|
-
[](
|
|
7
|
+
[](./LICENSE)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
registered.
|
|
11
|
-
- **Native Stage 3 decorators.** `@injectable`, `inject`, `optional`, `@postConstruct`, `@preDestroy` — no runtime
|
|
12
|
-
reflection tricks.
|
|
13
|
-
- **Fluent bindings.** Constants, classes, sync/async factories, aliases, named/tagged/predicate constraints, lifecycle
|
|
14
|
-
hooks.
|
|
15
|
-
- **Scopes with validation.** `singleton` / `scoped` / `transient`, plus `validate()` to catch captive dependencies
|
|
16
|
-
early.
|
|
17
|
-
- **Modules.** Bundle bindings into reusable units; load, unload, and compose them across containers.
|
|
18
|
-
- **Async-aware.** Async factories, deduped async singleton construction, and `await using` disposal.
|
|
9
|
+
## Overview
|
|
19
10
|
|
|
20
|
-
|
|
21
|
-
|
|
11
|
+
`@codefast/di` manages the services your app depends on. You describe how to build each service once, then ask a
|
|
12
|
+
container for it by a typed key. The container constructs that service — and everything it depends on — in the right
|
|
13
|
+
order.
|
|
22
14
|
|
|
23
|
-
|
|
15
|
+
Two calls carry the whole model: `bind` registers a service, and `resolve` returns a fully wired instance.
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
Use dependency injection when you want swappable implementations, scoping, and lifecycle handled for you, with the
|
|
18
|
+
wiring checked by the TypeScript compiler. Reach for plain `new` while a few objects still do the job; the library earns
|
|
19
|
+
its keep as the dependency graph grows.
|
|
20
|
+
|
|
21
|
+
- **Typed tokens.** `Token<Value>` flows through every `bind → resolve` path, so `resolve()` returns exactly the type
|
|
22
|
+
you registered.
|
|
23
|
+
- **Native Stage 3 decorators.** `@injectable`, `inject`, `optional`, `injectAll`, `@postConstruct`, and `@preDestroy`
|
|
24
|
+
declare dependencies explicitly — no runtime reflection.
|
|
25
|
+
- **Fluent bindings.** Constants, classes, sync and async factories, aliases, named/tagged/predicate constraints, and
|
|
26
|
+
lifecycle hooks compose in one invariant chain order.
|
|
27
|
+
- **Scopes with validation.** Choose `singleton`, `scoped`, or `transient`, and call `validate()` to catch captive
|
|
28
|
+
dependencies before the first request.
|
|
29
|
+
- **Modules and introspection.** Bundle bindings into reusable modules, and inspect a container or render its dependency
|
|
30
|
+
graph as DOT, Mermaid, Cytoscape, or React Flow.
|
|
28
31
|
|
|
29
32
|
## Installation
|
|
30
33
|
|
|
31
34
|
```bash
|
|
32
35
|
pnpm add @codefast/di
|
|
33
|
-
# or: npm install @codefast/di
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
`@codefast/di` requires Node.js 24 or later and TypeScript 5.9 or later, with native Stage 3 decorators. Leave
|
|
39
|
+
`experimentalDecorators` off — it's off by default. The package is published on 0.x and versioned on its own track:
|
|
40
|
+
breaking changes ship as minor versions, so pin the minor version when you need stability.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
37
43
|
|
|
38
|
-
```
|
|
44
|
+
```ts
|
|
39
45
|
import { Container, injectable, token } from "@codefast/di";
|
|
40
46
|
|
|
41
47
|
interface Logger {
|
|
@@ -68,37 +74,40 @@ container.rebind(LoggerToken).toConstantValue({
|
|
|
68
74
|
});
|
|
69
75
|
```
|
|
70
76
|
|
|
71
|
-
`@injectable([...])`
|
|
72
|
-
|
|
77
|
+
`@injectable([...])` declares a class's constructor dependencies, in parameter order. The decorator checks the list
|
|
78
|
+
against the constructor signature, so a dependency of the wrong type — or a list of the wrong length — is a compile-time
|
|
79
|
+
error.
|
|
73
80
|
|
|
74
81
|
## Tokens
|
|
75
82
|
|
|
76
|
-
A token pairs a name with a TypeScript type
|
|
83
|
+
A token is a typed key that identifies a service. It pairs a name with a TypeScript type, and it's the identity you bind
|
|
84
|
+
and resolve against. Tokens compare by reference, so declare each one once and reuse the `const`.
|
|
77
85
|
|
|
78
|
-
```
|
|
86
|
+
```ts
|
|
79
87
|
import { token } from "@codefast/di";
|
|
80
88
|
|
|
81
89
|
const DbToken = token<Database>("Database");
|
|
82
90
|
```
|
|
83
91
|
|
|
84
|
-
A class constructor
|
|
85
|
-
`container.resolve(UserService)`.
|
|
92
|
+
A class constructor works as a key too: `container.bind(UserService).toSelf()`, then `container.resolve(UserService)`.
|
|
86
93
|
|
|
87
94
|
## Bindings
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
| `.
|
|
96
|
-
| `.
|
|
97
|
-
| `.
|
|
98
|
-
| `.
|
|
99
|
-
| `.
|
|
100
|
-
|
|
101
|
-
|
|
96
|
+
A binding describes how the container produces a value for a token. You declare it as a chain, in one fixed order: a
|
|
97
|
+
strategy (the `to*` step, which produces the value), then optional constraints, a scope, and lifecycle hooks. Only
|
|
98
|
+
`container.bind(key).to*(…)` is required; everything after it is optional.
|
|
99
|
+
|
|
100
|
+
| Strategy | Produces |
|
|
101
|
+
| --------------------------------- | ----------------------------------------------------------------- |
|
|
102
|
+
| `.toConstantValue(value)` | A fixed value (always singleton) |
|
|
103
|
+
| `.toSelf()` / `.to(Constructor)` | A class instance built from its `@injectable` metadata |
|
|
104
|
+
| `.toDynamic(factory)` | A sync factory `(ctx: ResolutionContext) => Value` |
|
|
105
|
+
| `.toDynamicAsync(factory)` | An async factory — resolve it with the `*Async` container methods |
|
|
106
|
+
| `.toResolved(factory, deps)` | A factory called with its typed dependency tuple already resolved |
|
|
107
|
+
| `.toResolvedAsync(factory, deps)` | The same, returning a `Promise` |
|
|
108
|
+
| `.toAlias(targetToken)` | An alias — a redirect to another token's binding |
|
|
109
|
+
|
|
110
|
+
```ts
|
|
102
111
|
container.bind(ConfigToken).toConstantValue({ dbUrl: "postgres://…" });
|
|
103
112
|
|
|
104
113
|
container.bind(DbToken).toDynamicAsync(async (ctx) => {
|
|
@@ -109,75 +118,127 @@ container.bind(DbToken).toDynamicAsync(async (ctx) => {
|
|
|
109
118
|
|
|
110
119
|
container
|
|
111
120
|
.bind(UserServiceToken)
|
|
112
|
-
.toResolved((repo, config) => new UserService(repo, config), [UserRepository, ConfigToken]
|
|
121
|
+
.toResolved((repo, config) => new UserService(repo, config), [UserRepository, ConfigToken]);
|
|
113
122
|
```
|
|
114
123
|
|
|
115
124
|
### Scopes
|
|
116
125
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
|
121
|
-
|
|
|
126
|
+
A scope determines how long an instance lives and which container owns it. The default is `transient`, so a binding with
|
|
127
|
+
no scope produces a new instance every time.
|
|
128
|
+
|
|
129
|
+
| Scope | Lifetime |
|
|
130
|
+
| -------------- | ---------------------------------------------------------------------------------------- |
|
|
131
|
+
| `.singleton()` | One instance for the container that owns the binding; children resolve the same instance |
|
|
132
|
+
| `.scoped()` | One instance per child container — resolving from a container with no child scope throws |
|
|
133
|
+
| `.transient()` | A new instance on every resolution — the default |
|
|
122
134
|
|
|
123
|
-
```
|
|
135
|
+
```ts
|
|
124
136
|
container.bind(DbToken).toDynamic(createDb).singleton();
|
|
125
137
|
container.bind(RequestContextToken).toSelf().scoped();
|
|
126
138
|
```
|
|
127
139
|
|
|
140
|
+
> **Important.** Resolving a `scoped` binding from a container with no child scope throws `MissingScopeContextError`.
|
|
141
|
+
> Open a scope with [`createChild()`](#child-containers) first.
|
|
142
|
+
|
|
143
|
+
### Lifecycle hooks
|
|
144
|
+
|
|
145
|
+
A lifecycle hook runs your code as an instance is created or torn down. `.onActivation(fn)` runs right after an instance
|
|
146
|
+
is created, and may replace it; `.onDeactivation(fn)` runs when the owning container is disposed or the binding is
|
|
147
|
+
unbound. Both are also available container-wide, through `container.onActivation(token, fn)` and
|
|
148
|
+
`container.onDeactivation(token, fn)`:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
container
|
|
152
|
+
.bind(DbToken)
|
|
153
|
+
.toDynamicAsync(connectDb)
|
|
154
|
+
.singleton()
|
|
155
|
+
.onDeactivation((db) => db.close());
|
|
156
|
+
```
|
|
157
|
+
|
|
128
158
|
### Constraints
|
|
129
159
|
|
|
130
|
-
|
|
131
|
-
|
|
160
|
+
Several bindings can share one token, and a constraint decides which one a given `resolve` receives. A binding's set of
|
|
161
|
+
constraints is its slot — think of a slot as a labelled variant of the token.
|
|
162
|
+
|
|
163
|
+
**Named — the common case.** A named slot is keyed by a plain string. Declare it with `whenNamed`, and request it with
|
|
164
|
+
`{ name }`:
|
|
132
165
|
|
|
133
|
-
```
|
|
166
|
+
```ts
|
|
167
|
+
container.bind(LoggerToken).toConstantValue(consoleLogger).whenNamed("console");
|
|
168
|
+
container.bind(LoggerToken).toConstantValue(fileLogger).whenNamed("file");
|
|
169
|
+
|
|
170
|
+
container.resolve(LoggerToken, { name: "file" }); // → fileLogger
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Tagged — for typed, collision-proof keys.** A criterion is a `[key, value]` pair. Declare the key once with
|
|
174
|
+
`tag<Value>(name)`, then mint a criterion with `key.of(value)`. The bind site and the resolve site share the same typed
|
|
175
|
+
key: a key declared `tag<"s3" | "gcs">` refuses any other value, so the two sites can't drift apart.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
134
178
|
import { tag } from "@codefast/di";
|
|
135
179
|
|
|
136
180
|
const Provider = tag<"s3" | "gcs">("provider");
|
|
137
181
|
|
|
138
|
-
container.bind(LoggerToken).toConstantValue(fileLogger).whenNamed("file");
|
|
139
182
|
container.bind(StorageToken).to(S3Storage).whenTagged(Provider.of("s3"));
|
|
140
|
-
|
|
141
|
-
container.resolve(LoggerToken, { name: "file" });
|
|
142
|
-
container.resolve(StorageToken, { tag: Provider.of("s3") });
|
|
183
|
+
container.resolve(StorageToken, { tag: Provider.of("s3") }); // → S3Storage
|
|
143
184
|
```
|
|
144
185
|
|
|
145
|
-
|
|
146
|
-
value, so a bind site and a resolve site cannot drift apart silently. `key.of(value)` interns, so the same value always
|
|
147
|
-
yields the same criterion — which is what lets lookup compare by identity. Build a criterion by hand and it matches
|
|
148
|
-
nothing.
|
|
186
|
+
**How a request selects a slot.** In one line: a request matches a slot when it carries every tag the slot declares.
|
|
149
187
|
|
|
150
|
-
|
|
151
|
-
|
|
188
|
+
- Adding tags to a request makes it match more slots, not fewer — it's a superset filter.
|
|
189
|
+
- When several slots match, the slot declaring more of the request's tags wins (most-specific-wins).
|
|
190
|
+
- A tie between equally specific slots throws `AmbiguousBindingError`.
|
|
191
|
+
- A request with no criteria selects the binding marked `.whenDefault()` — or, equivalently, the binding that declares
|
|
192
|
+
no constraint at all.
|
|
152
193
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const Tier = tag<"premium" | "basic">("tier");
|
|
194
|
+
> **Note.** `key.of(value)` interns each value: the same value always yields the same criterion object, which lets
|
|
195
|
+
> lookup compare by identity. A criterion built by hand — not through `.of()` — matches nothing.
|
|
156
196
|
|
|
157
|
-
|
|
197
|
+
`{ tag: criterion }` and `{ tags: [criterion] }` are the same request — for `resolve`, and for `inject`, `optional`, and
|
|
198
|
+
`injectAll` alike. Chain `.whenTagged(...)` once per criterion a slot carries, and request several at once with
|
|
199
|
+
`{ tags: [...] }`.
|
|
158
200
|
|
|
159
|
-
|
|
160
|
-
|
|
201
|
+
**Predicate constraints — graph-aware selection.** When a slot isn't enough — when you need to choose based on _who_ is
|
|
202
|
+
resolving — pass a predicate to `.when(ctx => boolean)`. It runs at resolve time, after slot matching. These ready-made
|
|
203
|
+
predicates ship from the root entry:
|
|
161
204
|
|
|
162
|
-
|
|
163
|
-
|
|
205
|
+
| Predicate | Matches when |
|
|
206
|
+
| ------------------------------------ | ------------------------------------------------------ |
|
|
207
|
+
| `whenParentIs(token)` | the direct parent resolves `token` |
|
|
208
|
+
| `whenNoParentIs(token)` | there is no parent, or it resolves a different token |
|
|
209
|
+
| `whenAnyAncestorIs(token)` | some ancestor resolves `token` |
|
|
210
|
+
| `whenNoAncestorIs(token)` | no ancestor resolves `token` |
|
|
211
|
+
| `whenParentNamed(name)` | the parent's slot carries that name |
|
|
212
|
+
| `whenAnyAncestorNamed(name)` | some ancestor's slot carries that name |
|
|
213
|
+
| `whenParentTagged(criterion)` | the parent's slot carries that criterion |
|
|
214
|
+
| `whenAnyAncestorTagged(criterion)` | some ancestor's slot carries that criterion |
|
|
215
|
+
| `whenParentTaggedAll(criteria)` | the parent's slot carries all criteria in the array |
|
|
216
|
+
| `whenAnyAncestorTaggedAll(criteria)` | some ancestor's slot carries all criteria in the array |
|
|
164
217
|
|
|
165
|
-
For
|
|
166
|
-
`whenParentTagged` ship from the root entry (`import { whenParentIs } from "@codefast/di"`).
|
|
218
|
+
For the exact matching and most-specific-wins rules, see [`SPEC.md` → Slots and last-wins](./SPEC.md#slot-matching).
|
|
167
219
|
|
|
168
220
|
## Decorators
|
|
169
221
|
|
|
170
|
-
|
|
171
|
-
|
|
222
|
+
Decorators are optional: you can wire an entire app with explicit bindings and never write one. When you do reach for
|
|
223
|
+
them:
|
|
224
|
+
|
|
225
|
+
- `@injectable([...deps])` — declares a class's constructor dependencies, in parameter order.
|
|
226
|
+
- `inject(token, options)` — wraps one dependency with slot options (`name`, `tag`, `tags`).
|
|
227
|
+
- `optional(token)` — resolves to `undefined` when nothing is bound.
|
|
228
|
+
- `injectAll(token)` — collects every matching binding into an array.
|
|
229
|
+
- `@postConstruct()` — runs after wiring; `@preDestroy()` runs on disposal. An async `@postConstruct` needs
|
|
230
|
+
`resolveAsync`.
|
|
172
231
|
|
|
173
|
-
```
|
|
174
|
-
import { inject, injectable, optional, postConstruct, preDestroy } from "@codefast/di";
|
|
232
|
+
```ts
|
|
233
|
+
import { inject, injectable, injectAll, optional, postConstruct, preDestroy } from "@codefast/di";
|
|
175
234
|
|
|
176
|
-
@injectable([DbToken, optional(CacheToken)])
|
|
235
|
+
@injectable([DbToken, optional(CacheToken), injectAll(PluginToken), inject(LoggerToken, { name: "audit" })])
|
|
177
236
|
class UserRepository {
|
|
178
237
|
constructor(
|
|
179
238
|
private readonly db: Database,
|
|
180
|
-
private readonly cache
|
|
239
|
+
private readonly cache: Cache | undefined,
|
|
240
|
+
private readonly plugins: Array<Plugin>,
|
|
241
|
+
private readonly audit: Logger,
|
|
181
242
|
) {}
|
|
182
243
|
|
|
183
244
|
@postConstruct()
|
|
@@ -192,84 +253,109 @@ class UserRepository {
|
|
|
192
253
|
}
|
|
193
254
|
```
|
|
194
255
|
|
|
195
|
-
|
|
256
|
+
### Accessor injection
|
|
257
|
+
|
|
258
|
+
Accessor injection sets a property from the container instead of through the constructor. `inject` doubles as an
|
|
259
|
+
accessor decorator:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
import { inject, injectable, runWithContainer } from "@codefast/di";
|
|
196
263
|
|
|
197
|
-
```typescript
|
|
198
264
|
@injectable()
|
|
199
265
|
class Controller {
|
|
200
266
|
@inject(LoggerToken) accessor logger!: Logger;
|
|
201
267
|
}
|
|
268
|
+
|
|
269
|
+
const fromContainer = container.resolve(Controller);
|
|
270
|
+
const byHand = runWithContainer(container, () => new Controller());
|
|
202
271
|
```
|
|
203
272
|
|
|
204
|
-
An accessor resolves from the container that
|
|
205
|
-
|
|
206
|
-
|
|
273
|
+
An accessor resolves from the container that's constructing the instance. When something else owns the `new` — a router,
|
|
274
|
+
an ORM, a test helper — open that context with `runWithContainer`. Without one, the accessor throws
|
|
275
|
+
`MissingContainerContextError`. `getActiveContainer()` reads the open context.
|
|
207
276
|
|
|
208
|
-
|
|
209
|
-
metadata yourself:
|
|
277
|
+
### Auto-registration
|
|
210
278
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
279
|
+
To avoid binding classes one by one, let them register themselves.
|
|
280
|
+
`@injectable(deps, { autoRegister: registry, scope })` records the class in a registry from
|
|
281
|
+
`createAutoRegisterRegistry()`, and `container.loadAutoRegistered(registry)` binds the whole set in one call.
|
|
282
|
+
|
|
283
|
+
### Custom metadata
|
|
214
284
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
and the MetadataReader section of [SPEC.md](https://github.com/codefastlabs/codefast/blob/main/packages/di/SPEC.md).
|
|
285
|
+
Some classes you can't decorate — a dependency's class, generated code, plain JavaScript. Wire them by supplying their
|
|
286
|
+
metadata through a `MetadataReader`, passed as `Container.create({ metadataReader })`. A reader reports constructor
|
|
287
|
+
parameters, lifecycle method names, and `@inject` accessors; delegate misses to `defaultMetadataReader` so decorated
|
|
288
|
+
classes keep working. The reader is fixed when the container is created, and inherited by its children.
|
|
220
289
|
|
|
221
290
|
## Container
|
|
222
291
|
|
|
223
|
-
```
|
|
292
|
+
```ts
|
|
224
293
|
const container = Container.create();
|
|
225
294
|
|
|
226
295
|
container.resolve(ServiceToken); // throws TokenNotBoundError when unbound
|
|
227
296
|
container.resolveOptional(CacheToken); // undefined when unbound
|
|
228
297
|
container.resolveAll(HandlerToken); // every matching binding
|
|
298
|
+
container.has(ServiceToken); // true when this container or an ancestor binds it
|
|
229
299
|
|
|
230
300
|
const db = await container.resolveAsync(DbToken); // required for async bindings
|
|
231
301
|
```
|
|
232
302
|
|
|
233
|
-
|
|
234
|
-
|
|
303
|
+
### Sync vs async resolution
|
|
304
|
+
|
|
305
|
+
The rule is simple: if anything in the chain is async, resolve with an `*Async` method. A synchronous `resolve()` that
|
|
306
|
+
reaches an async factory — its own, or a dependency's — throws `AsyncResolutionError` rather than silently returning a
|
|
307
|
+
`Promise`.
|
|
308
|
+
|
|
309
|
+
| Sync | Async counterpart |
|
|
310
|
+
| ----------------- | ---------------------- |
|
|
311
|
+
| `resolve` | `resolveAsync` |
|
|
312
|
+
| `resolveOptional` | `resolveOptionalAsync` |
|
|
313
|
+
| `resolveAll` | `resolveAllAsync` |
|
|
314
|
+
|
|
315
|
+
An async `@postConstruct` or `onActivation` hook needs an `*Async` resolve too; on a synchronous path, it throws
|
|
316
|
+
`AsyncActivationError`. `initializeAsync()` warms every eligible singleton up front, so later `resolve()` calls stay
|
|
317
|
+
synchronous.
|
|
235
318
|
|
|
236
319
|
### Child containers
|
|
237
320
|
|
|
238
|
-
|
|
239
|
-
|
|
321
|
+
A child container implements the request-scope pattern. It falls through to its parent's bindings and shares the
|
|
322
|
+
parent's singletons, while each `scoped` binding gets a fresh instance per child.
|
|
240
323
|
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
324
|
+
```ts
|
|
325
|
+
{
|
|
326
|
+
await using requestContainer = container.createChild();
|
|
327
|
+
requestContainer.bind(RequestIdToken).toConstantValue(crypto.randomUUID());
|
|
328
|
+
const service = requestContainer.resolve(RequestScopedService);
|
|
329
|
+
} // dispose() runs here and releases what this child owns
|
|
245
330
|
```
|
|
246
331
|
|
|
247
332
|
### Validation
|
|
248
333
|
|
|
249
|
-
|
|
250
|
-
binding.
|
|
334
|
+
A captive dependency is a long-lived binding that holds a shorter-lived one — a `singleton` that depends on a `scoped`
|
|
335
|
+
or `transient` binding — which silently freezes that dependency for the singleton's whole life. `validate()` fails fast
|
|
336
|
+
on captive dependencies, and on constraints no request can satisfy, before the first resolve.
|
|
251
337
|
|
|
252
|
-
```
|
|
338
|
+
```ts
|
|
253
339
|
container.validate(); // throws ScopeViolationError on the first violation
|
|
254
340
|
```
|
|
255
341
|
|
|
256
342
|
### Disposal
|
|
257
343
|
|
|
258
|
-
`Container` implements `AsyncDisposable`, so `await using` runs deactivation
|
|
344
|
+
`Container` implements `AsyncDisposable`, so `await using` runs every deactivation hook automatically as the block
|
|
345
|
+
exits. Synchronous `using` isn't supported — `onDeactivation` may be async — and `Symbol.dispose` throws
|
|
346
|
+
`SyncDisposalNotSupportedError`.
|
|
259
347
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
} // dispose() runs here
|
|
266
|
-
```
|
|
348
|
+
### Introspection
|
|
349
|
+
|
|
350
|
+
`container.inspect()` returns a `ContainerSnapshot`; `container.lookupBindings(token)` returns the snapshots of one
|
|
351
|
+
token's bindings; and `container.generateDependencyGraph()` returns a JSON graph. Adapters render that graph for common
|
|
352
|
+
viewers: `toDotGraph`, `toMermaidGraph`, `toCytoscapeGraph`, and `toReactFlowGraph`.
|
|
267
353
|
|
|
268
354
|
## Modules
|
|
269
355
|
|
|
270
|
-
|
|
356
|
+
A module is a reusable, stateless bundle of related bindings. Group them once, then load them into any container.
|
|
271
357
|
|
|
272
|
-
```
|
|
358
|
+
```ts
|
|
273
359
|
import { Container, Module } from "@codefast/di";
|
|
274
360
|
|
|
275
361
|
const InfrastructureModule = Module.create("Infra", (api) => {
|
|
@@ -284,65 +370,62 @@ const AppModule = Module.create("App", (api) => {
|
|
|
284
370
|
const container = Container.fromModules(AppModule);
|
|
285
371
|
```
|
|
286
372
|
|
|
287
|
-
`Module.createAsync`
|
|
288
|
-
`Container.fromModulesAsync` or `container.loadAsync`. Modules are ref-counted:
|
|
289
|
-
removes bindings
|
|
373
|
+
`Module.createAsync` lets you await during setup — for remote config or connections. Load those with
|
|
374
|
+
`Container.fromModulesAsync` or `container.loadAsync`. Modules are ref-counted: loading one twice counts once, and
|
|
375
|
+
`unload` removes its bindings only when the count reaches zero.
|
|
290
376
|
|
|
291
377
|
## Errors
|
|
292
378
|
|
|
293
|
-
Every error extends `DiError` and carries a stable `code
|
|
294
|
-
|
|
295
|
-
|
|
379
|
+
Every error extends `DiError` and carries a stable `code`, so you can branch on the code rather than the message:
|
|
380
|
+
|
|
381
|
+
| Error | Code | Raised when |
|
|
382
|
+
| ------------------------------ | --------------------------- | -------------------------------------------------------------------------- |
|
|
383
|
+
| `TokenNotBoundError` | `TOKEN_NOT_BOUND` | No binding exists for the token in the container chain |
|
|
384
|
+
| `NoMatchingBindingError` | `NO_MATCHING_BINDING` | The token has bindings but none matches the request's slot |
|
|
385
|
+
| `AmbiguousBindingError` | `AMBIGUOUS_BINDING` | Several bindings match with no more-specific winner |
|
|
386
|
+
| `CircularDependencyError` | `CIRCULAR_DEPENDENCY` | A cycle appears on the resolution path |
|
|
387
|
+
| `AsyncResolutionError` | `ASYNC_RESOLUTION` | A sync `resolve()` reaches an async factory |
|
|
388
|
+
| `AsyncActivationError` | `ASYNC_ACTIVATION` | A `@postConstruct` or `onActivation` hook returns a promise on a sync path |
|
|
389
|
+
| `ScopeViolationError` | `SCOPE_VIOLATION` | `validate()` finds a captive dependency |
|
|
390
|
+
| `MissingScopeContextError` | `MISSING_SCOPE_CONTEXT` | A `scoped` binding is resolved outside a child container |
|
|
391
|
+
| `MissingContainerContextError` | `MISSING_CONTAINER_CONTEXT` | An `@inject` accessor initializes with no container open |
|
|
392
|
+
| `DisposedContainerError` | `DISPOSED_CONTAINER` | A disposed container is used |
|
|
393
|
+
|
|
394
|
+
The full taxonomy — including `MissingMetadataError`, `InvalidMetadataError`, `RebindUnboundTokenError`,
|
|
395
|
+
`AsyncModuleLoadError`, and the rest — is exported from the root entry and from `@codefast/di/errors/errors`.
|
|
296
396
|
|
|
297
397
|
## Subpath exports
|
|
298
398
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
tree-shakeable subpath mirroring the source layout:
|
|
399
|
+
Prefer the root entry: it re-exports the whole public API. Reach for a subpath only to trim a bundle, or to pull in
|
|
400
|
+
something the root doesn't surface.
|
|
302
401
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
- **Introspection** ships at flat specifiers, without the directory prefix — `@codefast/di/inspector`,
|
|
309
|
-
`/dependency-graph`, and the graph adapters (`@codefast/di/graph-adapters/{dot,cytoscape,mermaid,reactflow}`) for
|
|
310
|
-
visualizing `container.generateDependencyGraph()` output
|
|
311
|
-
- **Decorators & metadata** under `/decorators/*` and `/metadata/*`
|
|
402
|
+
Every module is also published as a subpath that mirrors the source layout: the model under `@codefast/di/core/*`
|
|
403
|
+
(`core/token`, `core/tag`, `core/module`, …), errors under `errors/*`, the runtime under `container/*`, `injection/*`,
|
|
404
|
+
`lifecycle/*`, and `resolution/*` (for example `@codefast/di/resolution/select/constraints`), and decorators and
|
|
405
|
+
metadata under `decorators/*` and `metadata/*`. Introspection ships at flat specifiers: `@codefast/di/inspector`,
|
|
406
|
+
`@codefast/di/dependency-graph`, and `@codefast/di/graph-adapters/{dot,mermaid,cytoscape,reactflow}`.
|
|
312
407
|
|
|
313
408
|
## Benchmarks
|
|
314
409
|
|
|
315
|
-
A
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
## Learning how it works
|
|
330
|
-
|
|
331
|
-
Curious how the engine is built, or want to learn from it?
|
|
332
|
-
[LEARNING.md](https://github.com/codefastlabs/codefast/blob/main/packages/di/LEARNING.md) is a guided read of the real
|
|
333
|
-
architectural patterns, design patterns, algorithms, TypeScript techniques, and performance work in this codebase — a
|
|
334
|
-
tour of one `resolve()` call, then a catalogue by topic, each pointing at the code. For the exact behavioural contract
|
|
335
|
-
see [SPEC.md](https://github.com/codefastlabs/codefast/blob/main/packages/di/SPEC.md); for the invariants the engine
|
|
336
|
-
depends on see [ARCHITECTURE.md](https://github.com/codefastlabs/codefast/blob/main/packages/di/ARCHITECTURE.md).
|
|
410
|
+
A first-party benchmark suite lives in the monorepo, at [`benchmarks/di-inversify`](../../benchmarks/di-inversify). It
|
|
411
|
+
runs the same workloads through `@codefast/di`, InversifyJS, Awilix, and tsyringe, and its `RESULTS.md` ledger records
|
|
412
|
+
the numbers alongside the method that produced them. Run it yourself rather than taking any figure on faith.
|
|
413
|
+
|
|
414
|
+
## Documentation
|
|
415
|
+
|
|
416
|
+
- [Rendered docs on codefastlabs.com](https://codefastlabs.com/docs/di)
|
|
417
|
+
- [`SPEC.md`](./SPEC.md) — the behavioural contract: public API, semantics, and errors.
|
|
418
|
+
- [`ARCHITECTURE.md`](./ARCHITECTURE.md) — the internal shape and the invariants the hot paths depend on.
|
|
419
|
+
- [`LEARNING.md`](./LEARNING.md) — a guided tour of the techniques the engine applies, pointing at the code.
|
|
420
|
+
- [`examples/`](./examples/README.md) — runnable examples from basic tokens to a multi-file Ports & Adapters app.
|
|
421
|
+
- [`CONTRIBUTING.md`](./CONTRIBUTING.md) — the package workflow: build, exports mirror, tests, and the perf guard.
|
|
422
|
+
- [`CHANGELOG.md`](./CHANGELOG.md) — release history.
|
|
337
423
|
|
|
338
424
|
## Contributing
|
|
339
425
|
|
|
340
|
-
|
|
341
|
-
[CONTRIBUTING.md](
|
|
342
|
-
build, exports mirror, tests, the mandatory perf-guard for resolver changes, and the release gate.
|
|
426
|
+
See the repo-wide [contributing guide](../../CONTRIBUTING.md) for setup and conventions, and this package's
|
|
427
|
+
[`CONTRIBUTING.md`](./CONTRIBUTING.md) for the resolver perf guard and the exports mirror.
|
|
343
428
|
|
|
344
429
|
## License
|
|
345
430
|
|
|
346
|
-
[MIT](
|
|
347
|
-
[codefast monorepo](https://github.com/codefastlabs/codefast). See
|
|
348
|
-
[CHANGELOG.md](https://github.com/codefastlabs/codefast/blob/main/packages/di/CHANGELOG.md) for release history.
|
|
431
|
+
Released under the [MIT License](./LICENSE).
|
|
@@ -37,5 +37,4 @@ export declare function getActiveContainer(): Container | undefined;
|
|
|
37
37
|
*
|
|
38
38
|
* @since 0.6.0
|
|
39
39
|
*/
|
|
40
|
-
export declare function getAmbientResolution(): AmbientResolution | undefined;
|
|
41
|
-
//# sourceMappingURL=active-container.d.ts.map
|
|
40
|
+
export declare function getAmbientResolution(): AmbientResolution | undefined;
|
|
@@ -56,5 +56,4 @@ export declare class BindingChain<Value> implements AliasBindingBuilder, Binding
|
|
|
56
56
|
onActivation(fn: ActivationHandler<Value>): this;
|
|
57
57
|
onDeactivation(fn: DeactivationHandler<Value>): this;
|
|
58
58
|
id(): BindingIdentifier;
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=binding-builders.d.ts.map
|
|
59
|
+
}
|