@frontmcp/di 1.9.6 → 1.9.7
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/README.md +61 -28
- package/esm/package.json +5 -4
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,58 +1,91 @@
|
|
|
1
1
|
# @frontmcp/di
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The dependency injection container behind FrontMCP. This is an internal package: `@frontmcp/sdk` uses it to build providers and registries, and installs it for you. In a FrontMCP server, declare shared services with `@Provider` and read them with `this.get()` from `@frontmcp/sdk` instead. The container has no FrontMCP-specific code, so you can also use it on its own in any TypeScript project.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/@frontmcp/di) [](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
|
|
8
6
|
|
|
9
7
|
## Install
|
|
10
8
|
|
|
11
9
|
```bash
|
|
12
|
-
npm install @frontmcp/di reflect-metadata
|
|
10
|
+
npm install @frontmcp/di @frontmcp/lazy-zod zod reflect-metadata
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- **Type-safe DI** — class tokens with configurable prefixes ([docs][docs-providers])
|
|
18
|
-
- **Scoped providers** — GLOBAL and CONTEXT scopes
|
|
19
|
-
- **Hierarchical registries** — parent/child container adoption
|
|
20
|
-
- **Indexed lookups** — O(1) registry queries via `IndexedRegistry`
|
|
21
|
-
- **Change events** — subscribe to registry mutations
|
|
22
|
-
- **Token factory** — `createTokenFactory({ prefix })` for Symbol-based tokens
|
|
13
|
+
`@frontmcp/lazy-zod` (which needs `zod` 4) and `reflect-metadata` are peer dependencies. Import `reflect-metadata` once, before anything else. It needs Node.js 24 or later.
|
|
23
14
|
|
|
24
|
-
##
|
|
15
|
+
## Usage
|
|
25
16
|
|
|
26
17
|
```ts
|
|
27
18
|
import 'reflect-metadata';
|
|
28
19
|
|
|
29
20
|
import { createTokenFactory, DiContainer, ProviderScope } from '@frontmcp/di';
|
|
30
21
|
|
|
31
|
-
const tokens = createTokenFactory({ prefix: '
|
|
22
|
+
const tokens = createTokenFactory({ prefix: 'Desk' });
|
|
23
|
+
const DESK_URL = tokens.type('DeskUrl');
|
|
24
|
+
|
|
25
|
+
class TicketStore {
|
|
26
|
+
static metadata = { name: 'TicketStore', scope: ProviderScope.GLOBAL };
|
|
27
|
+
readonly tickets = new Map<string, string>();
|
|
28
|
+
}
|
|
32
29
|
|
|
33
|
-
class
|
|
34
|
-
|
|
30
|
+
class TicketClient {
|
|
31
|
+
constructor(
|
|
32
|
+
readonly store: TicketStore,
|
|
33
|
+
readonly baseUrl: string,
|
|
34
|
+
) {}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const container = new DiContainer([
|
|
37
|
+
const container = new DiContainer([
|
|
38
|
+
TicketStore,
|
|
39
|
+
{ provide: DESK_URL, useValue: 'https://desk.example.com' },
|
|
40
|
+
{
|
|
41
|
+
provide: TicketClient,
|
|
42
|
+
inject: () => [TicketStore, DESK_URL],
|
|
43
|
+
useFactory: (store: TicketStore, baseUrl: string) => new TicketClient(store, baseUrl),
|
|
44
|
+
},
|
|
45
|
+
]);
|
|
46
|
+
|
|
38
47
|
await container.ready;
|
|
39
|
-
|
|
48
|
+
|
|
49
|
+
const client = container.get(TicketClient);
|
|
40
50
|
```
|
|
41
51
|
|
|
52
|
+
### Providers
|
|
53
|
+
|
|
54
|
+
| Form | How it's built |
|
|
55
|
+
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `MyClass` | With `new`. An optional `static metadata = { name, scope }` names it and sets its scope. Constructor parameters are injected when TypeScript records their types, which it does for a decorated class with `emitDecoratorMetadata` on. |
|
|
57
|
+
| `@AsyncWith(() => [DepA, DepB])` on a class | By calling its static `with(depA, depB)`, which may be async. |
|
|
58
|
+
| `{ provide, useValue }` | The value itself. |
|
|
59
|
+
| `{ provide, useFactory, inject }` | By calling `useFactory` with the providers `inject()` returns, in order. |
|
|
60
|
+
| `{ provide, useClass }` | Like a class, registered under `provide`. |
|
|
61
|
+
|
|
62
|
+
`provide` is a class, a symbol or a string. `createTokenFactory({ prefix })` makes symbols with `Symbol.for()`, so two copies of a package in one process share them: `tokens.type('DeskUrl')` is `Symbol.for('Desk:type:DeskUrl')`.
|
|
63
|
+
|
|
64
|
+
### Scopes
|
|
65
|
+
|
|
66
|
+
- `ProviderScope.GLOBAL` (the default): one instance, built in dependency order when the container starts. `await container.ready`, then read it with `container.get(token)`, or `container.tryGet(token)`, which returns `undefined` instead of throwing.
|
|
67
|
+
- `ProviderScope.CONTEXT`: one instance per context, like a request or a session. Build a context with `const views = await container.buildViews(key)`, then read it with `container.getScoped(token, views)`.
|
|
68
|
+
|
|
69
|
+
A `GLOBAL` provider can't depend on a `CONTEXT` one, and the container throws on dependency cycles.
|
|
70
|
+
|
|
71
|
+
### Hierarchy and registries
|
|
72
|
+
|
|
73
|
+
`new DiContainer(providers, parent)` looks up tokens it doesn't have in `parent`. The package also exports the registry base classes FrontMCP's own registries extend: `RegistryAbstract`, `SimpleRegistry`, and `IndexedRegistry`, which indexes entries by ID, name and owner, adopts child registries, and emits change events to `subscribe()` callbacks.
|
|
74
|
+
|
|
42
75
|
## Docs
|
|
43
76
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
| Providers & DI | [Providers][docs-providers] |
|
|
77
|
+
- [`@Provider`](https://frontmcp.dev/reference/sdk/provider): providers in a FrontMCP server, built on this container
|
|
78
|
+
- [Sharing state with providers](https://frontmcp.dev/learn/sharing-state-with-providers): a step-by-step guide
|
|
47
79
|
|
|
48
|
-
## Related
|
|
80
|
+
## Related packages
|
|
49
81
|
|
|
50
|
-
- [`@frontmcp/sdk`](
|
|
82
|
+
- [`@frontmcp/sdk`](https://www.npmjs.com/package/@frontmcp/sdk): the framework. Use its `@Provider` in a FrontMCP server.
|
|
83
|
+
- [`@frontmcp/lazy-zod`](https://www.npmjs.com/package/@frontmcp/lazy-zod): the Zod used for `providerMetadataSchema`.
|
|
51
84
|
|
|
52
|
-
##
|
|
85
|
+
## Contributing
|
|
53
86
|
|
|
54
|
-
|
|
87
|
+
Source: [`libs/di`](https://github.com/agentfront/frontmcp/tree/main/libs/di). Issues and pull requests are welcome; see [CONTRIBUTING.md](https://github.com/agentfront/frontmcp/blob/main/CONTRIBUTING.md).
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
## License
|
|
57
90
|
|
|
58
|
-
[
|
|
91
|
+
Apache-2.0. See [LICENSE](https://github.com/agentfront/frontmcp/blob/main/LICENSE).
|
package/esm/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/di",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.7",
|
|
4
4
|
"description": "Generic dependency injection container and registry utilities for TypeScript applications",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"typescript",
|
|
14
14
|
"decorators",
|
|
15
15
|
"reflect-metadata",
|
|
16
|
-
"inversion-of-control"
|
|
16
|
+
"inversion-of-control",
|
|
17
|
+
"frontmcp"
|
|
17
18
|
],
|
|
18
19
|
"repository": {
|
|
19
20
|
"type": "git",
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
"bugs": {
|
|
24
25
|
"url": "https://github.com/agentfront/frontmcp/issues"
|
|
25
26
|
},
|
|
26
|
-
"homepage": "https://
|
|
27
|
+
"homepage": "https://frontmcp.dev",
|
|
27
28
|
"type": "module",
|
|
28
29
|
"main": "../index.js",
|
|
29
30
|
"module": "./index.mjs",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"node": ">=24.0.0"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
|
-
"@frontmcp/lazy-zod": "1.9.
|
|
51
|
+
"@frontmcp/lazy-zod": "1.9.7",
|
|
51
52
|
"reflect-metadata": "^0.2.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/di",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.7",
|
|
4
4
|
"description": "Generic dependency injection container and registry utilities for TypeScript applications",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"typescript",
|
|
14
14
|
"decorators",
|
|
15
15
|
"reflect-metadata",
|
|
16
|
-
"inversion-of-control"
|
|
16
|
+
"inversion-of-control",
|
|
17
|
+
"frontmcp"
|
|
17
18
|
],
|
|
18
19
|
"repository": {
|
|
19
20
|
"type": "git",
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
"bugs": {
|
|
24
25
|
"url": "https://github.com/agentfront/frontmcp/issues"
|
|
25
26
|
},
|
|
26
|
-
"homepage": "https://
|
|
27
|
+
"homepage": "https://frontmcp.dev",
|
|
27
28
|
"type": "commonjs",
|
|
28
29
|
"main": "./index.js",
|
|
29
30
|
"module": "./esm/index.mjs",
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
"node": ">=24.0.0"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
|
-
"@frontmcp/lazy-zod": "1.9.
|
|
51
|
+
"@frontmcp/lazy-zod": "1.9.7",
|
|
51
52
|
"reflect-metadata": "^0.2.0"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|