@venizia/ignis-docs 0.2.0 → 0.2.1-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/README.md +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +22 -11
- package/content/best-practices/architecture-decisions.md +29 -16
- package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
- package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
- package/content/best-practices/code-style-standards/control-flow.md +33 -1
- package/content/best-practices/code-style-standards/documentation.md +28 -8
- package/content/best-practices/code-style-standards/function-patterns.md +15 -4
- package/content/best-practices/code-style-standards/index.md +7 -2
- package/content/best-practices/code-style-standards/naming-conventions.md +26 -2
- package/content/best-practices/code-style-standards/route-definitions.md +9 -5
- package/content/best-practices/code-style-standards/tooling.md +14 -1
- package/content/best-practices/code-style-standards/type-safety.md +39 -6
- package/content/best-practices/common-pitfalls.md +59 -35
- package/content/best-practices/contribution-workflow.md +6 -2
- package/content/best-practices/data-modeling.md +78 -62
- package/content/best-practices/deployment-strategies.md +56 -19
- package/content/best-practices/error-handling.md +182 -93
- package/content/best-practices/index.md +6 -0
- package/content/best-practices/performance-optimization.md +26 -13
- package/content/best-practices/security-guidelines.md +35 -9
- package/content/best-practices/testing-strategies.md +7 -2
- package/content/best-practices/troubleshooting-tips.md +27 -17
- package/content/extensions/components/api-reference.md +107 -322
- package/content/extensions/components/authentication/api.md +454 -603
- package/content/extensions/components/authentication/errors.md +121 -498
- package/content/extensions/components/authentication/index.md +88 -801
- package/content/extensions/components/authentication/usage.md +207 -956
- package/content/extensions/components/authorization/api.md +736 -656
- package/content/extensions/components/authorization/errors.md +168 -206
- package/content/extensions/components/authorization/index.md +82 -797
- package/content/extensions/components/authorization/usage.md +194 -527
- package/content/extensions/components/health-check.md +71 -243
- package/content/extensions/components/mail/api.md +504 -287
- package/content/extensions/components/mail/errors.md +73 -61
- package/content/extensions/components/mail/index.md +96 -467
- package/content/extensions/components/mail/usage.md +130 -172
- package/content/extensions/components/request-tracker.md +66 -173
- package/content/extensions/components/socket-io/api.md +195 -13
- package/content/extensions/components/socket-io/errors.md +3 -3
- package/content/extensions/components/socket-io/index.md +50 -337
- package/content/extensions/components/socket-io/usage.md +143 -26
- package/content/extensions/components/static-asset/api.md +410 -142
- package/content/extensions/components/static-asset/errors.md +110 -53
- package/content/extensions/components/static-asset/index.md +79 -608
- package/content/extensions/components/static-asset/usage.md +180 -300
- package/content/extensions/components/websocket/api.md +275 -399
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +74 -407
- package/content/extensions/components/websocket/usage.md +110 -341
- package/content/extensions/helpers/cron/index.md +51 -160
- package/content/extensions/helpers/crypto/index.md +62 -483
- package/content/extensions/helpers/crypto/reference.md +456 -0
- package/content/extensions/helpers/env/index.md +60 -178
- package/content/extensions/helpers/error/index.md +221 -207
- package/content/extensions/helpers/inversion/index.md +65 -556
- package/content/extensions/helpers/inversion/reference.md +522 -0
- package/content/extensions/helpers/kafka/admin.md +20 -1
- package/content/extensions/helpers/kafka/compile-binary.md +41 -35
- package/content/extensions/helpers/kafka/consumer.md +54 -20
- package/content/extensions/helpers/kafka/examples.md +21 -16
- package/content/extensions/helpers/kafka/index.md +80 -610
- package/content/extensions/helpers/kafka/producer.md +134 -5
- package/content/extensions/helpers/kafka/schema-registry.md +45 -70
- package/content/extensions/helpers/logger/hf-logger.md +193 -0
- package/content/extensions/helpers/logger/index.md +64 -563
- package/content/extensions/helpers/logger/pino.md +85 -0
- package/content/extensions/helpers/logger/reference.md +746 -0
- package/content/extensions/helpers/network/api.md +241 -195
- package/content/extensions/helpers/network/index.md +72 -530
- package/content/extensions/helpers/queue/index.md +72 -900
- package/content/extensions/helpers/queue/reference.md +467 -0
- package/content/extensions/helpers/redis/index.md +73 -645
- package/content/extensions/helpers/redis/reference.md +727 -0
- package/content/extensions/helpers/secrets/index.md +66 -0
- package/content/extensions/helpers/socket-io/api.md +305 -203
- package/content/extensions/helpers/socket-io/index.md +66 -432
- package/content/extensions/helpers/storage/api.md +564 -462
- package/content/extensions/helpers/storage/index.md +77 -573
- package/content/extensions/helpers/types/index.md +66 -499
- package/content/extensions/helpers/types/reference.md +650 -0
- package/content/extensions/helpers/uid/index.md +58 -227
- package/content/extensions/helpers/websocket/api.md +329 -216
- package/content/extensions/helpers/websocket/index.md +65 -503
- package/content/extensions/helpers/worker-thread/index.md +58 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/search-typesense.md +3 -3
- package/content/guides/core-concepts/persistent/transactions.md +1 -1
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/migrations/redis-helpers-migration.md +1 -1
- package/content/guides/migrations/unified-connectors-migration.md +2 -2
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/references/base/application.md +1 -1
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/datasources-reference.md +599 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +17 -39
- package/content/references/base/filter-system/application-usage.md +69 -121
- package/content/references/base/filter-system/array-operators.md +12 -0
- package/content/references/base/filter-system/comparison-operators.md +12 -0
- package/content/references/base/filter-system/default-filter.md +136 -348
- package/content/references/base/filter-system/fields-order-pagination.md +38 -16
- package/content/references/base/filter-system/index.md +106 -257
- package/content/references/base/filter-system/json-filtering.md +12 -2
- package/content/references/base/filter-system/list-operators.md +16 -2
- package/content/references/base/filter-system/logical-operators.md +13 -0
- package/content/references/base/filter-system/null-operators.md +13 -0
- package/content/references/base/filter-system/pattern-matching.md +12 -0
- package/content/references/base/filter-system/quick-reference.md +11 -2
- package/content/references/base/filter-system/range-operators.md +12 -0
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +156 -233
- package/content/references/base/middlewares.md +35 -21
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +80 -1452
- package/content/references/base/repositories/advanced.md +156 -192
- package/content/references/base/repositories/index.md +77 -650
- package/content/references/base/repositories/mixins.md +22 -18
- package/content/references/base/repositories/relations.md +123 -171
- package/content/references/base/repositories/soft-deletable.md +58 -56
- package/content/references/base/secrets.md +263 -0
- package/content/references/base/services.md +2 -2
- package/content/references/configuration/environment-variables.md +48 -4
- package/content/references/configuration/index.md +49 -31
- package/content/references/quick-reference.md +3 -16
- package/content/references/utilities/crypto.md +35 -76
- package/content/references/utilities/date.md +33 -73
- package/content/references/utilities/index.md +1 -1
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +29 -62
- package/content/references/utilities/parse.md +34 -64
- package/content/references/utilities/performance.md +33 -58
- package/content/references/utilities/promise.md +28 -62
- package/content/references/utilities/request.md +57 -218
- package/content/references/utilities/schema.md +43 -137
- package/content/references/utilities/statuses-reference.md +361 -0
- package/content/references/utilities/statuses.md +63 -667
- package/package.json +8 -8
|
@@ -1,616 +1,125 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Standalone IoC container with decorator-based injection
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Inversion (DI)
|
|
3
|
+
description: Standalone IoC container with decorator-based injection and a fluent binding API
|
|
4
|
+
difficulty: intermediate
|
|
5
|
+
---
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|------|-------|
|
|
9
|
-
| **Package** | `@venizia/ignis-inversion` |
|
|
10
|
-
| **Classes** | `Container`, `Binding`, `MetadataRegistry` |
|
|
11
|
-
| **Decorators** | `@inject`, `@injectable` |
|
|
12
|
-
| **Runtimes** | Both (Bun and Node.js) |
|
|
13
|
-
|
|
14
|
-
#### Import Paths
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
import {
|
|
18
|
-
Container,
|
|
19
|
-
Binding,
|
|
20
|
-
MetadataRegistry,
|
|
21
|
-
metadataRegistry,
|
|
22
|
-
inject,
|
|
23
|
-
injectable,
|
|
24
|
-
BindingKeys,
|
|
25
|
-
BindingScopes,
|
|
26
|
-
BindingValueTypes,
|
|
27
|
-
MetadataKeys,
|
|
28
|
-
BaseHelper,
|
|
29
|
-
ApplicationError,
|
|
30
|
-
getError,
|
|
31
|
-
ErrorSchema,
|
|
32
|
-
Logger,
|
|
33
|
-
} from '@venizia/ignis-inversion';
|
|
34
|
-
|
|
35
|
-
import type {
|
|
36
|
-
TNullable,
|
|
37
|
-
ValueOrPromise,
|
|
38
|
-
ValueOf,
|
|
39
|
-
TClass,
|
|
40
|
-
TConstructor,
|
|
41
|
-
TAbstractConstructor,
|
|
42
|
-
TConstValue,
|
|
43
|
-
TBindingScope,
|
|
44
|
-
TBindingValueType,
|
|
45
|
-
IProvider,
|
|
46
|
-
IInjectMetadata,
|
|
47
|
-
IPropertyMetadata,
|
|
48
|
-
IInjectableMetadata,
|
|
49
|
-
} from '@venizia/ignis-inversion';
|
|
50
|
-
```
|
|
7
|
+
# Inversion (DI)
|
|
51
8
|
|
|
52
|
-
|
|
53
|
-
> The framework package `@venizia/ignis` re-exports DI-specific symbols (`Binding`, `BindingKeys`, `BindingScopes`, `BindingValueTypes`, `IProvider`, `isClass`, `isClassProvider`, `TBindingScope`, `TBindingValueType`, `IBindingTag`) from `@venizia/ignis-inversion` and adds higher-level helpers (`app.controller()`, `app.service()`, etc.). All types from inversion are also available via type-only re-exports.
|
|
9
|
+
`@venizia/ignis-inversion` is the standalone IoC container - decorator-based injection, a fluent binding API, and singleton/transient scoping - that every other IGNIS package builds on.
|
|
54
10
|
|
|
55
|
-
##
|
|
11
|
+
## In one example
|
|
56
12
|
|
|
57
|
-
|
|
13
|
+
The smallest real use: bind a class with constructor injection, then resolve it through the container.
|
|
58
14
|
|
|
59
15
|
```typescript
|
|
60
|
-
import { Container } from '@venizia/ignis-inversion';
|
|
61
|
-
|
|
62
|
-
const container = new Container({ scope: 'MyApp' });
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
The `scope` parameter is optional and defaults to `'Container'`. It is used for logging and error context only.
|
|
16
|
+
import { Container, inject, BindingScopes } from '@venizia/ignis-inversion';
|
|
66
17
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
import { Container, BindingScopes } from '@venizia/ignis-inversion';
|
|
18
|
+
class UserService {
|
|
19
|
+
constructor(@inject({ key: 'config.appName' }) private appName: string) {}
|
|
20
|
+
}
|
|
71
21
|
|
|
72
22
|
const container = new Container({ scope: 'MyApp' });
|
|
73
23
|
|
|
74
|
-
|
|
24
|
+
container.bind<string>({ key: 'config.appName' }).toValue('MyApp');
|
|
75
25
|
container.bind<UserService>({ key: 'services.UserService' })
|
|
76
26
|
.toClass(UserService)
|
|
77
27
|
.setScope(BindingScopes.SINGLETON);
|
|
78
28
|
|
|
79
|
-
// Resolve the dependency
|
|
80
29
|
const userService = container.get<UserService>({ key: 'services.UserService' });
|
|
81
30
|
```
|
|
82
31
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
### Binding Values
|
|
32
|
+
A class needs no decorator to be bindable - the binding is always created explicitly with `container.bind()`, and scope is set on the binding via `setScope()`. The framework layer (`@venizia/ignis`) creates these bindings for you for controllers, services, and repositories via `app.controller()` / `app.service()` / `@repository`.
|
|
86
33
|
|
|
87
|
-
|
|
34
|
+
## How it works
|
|
88
35
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
container.
|
|
92
|
-
|
|
36
|
+
- **Three ways to resolve a binding.** `toClass` (container instantiates with DI), `toValue` (returned as-is), `toProvider` (factory function or `IProvider` class). All `Binding` setters return `this`, so calls chain.
|
|
37
|
+
- **Instantiation is two-phase.** Constructor injection runs first, reading `@inject` metadata by parameter index and passing resolved values as constructor args; property injection runs second, assigning each `@inject`-decorated property on the built instance. `container.resolve(cls)` and `container.instantiate(cls)` are the same method - `resolve` is an alias.
|
|
38
|
+
- **Every constructor parameter must carry `@inject`.** The metadata array is index-keyed - an undecorated parameter leaves a hole the container has no way to fill. `instantiate()` refuses the class by name and parameter index rather than passing `undefined`.
|
|
39
|
+
- **Namespaces auto-tag bindings.** A key like `services.UserService` tags the binding `services` automatically; `setTags()` adds more. `findByTag()` queries by tag, with an `exclude` list.
|
|
40
|
+
- **Keys** can be a `string`, a `symbol`, or `{ namespace, key }` (built into a dotted string via `BindingKeys.build`).
|
|
93
41
|
|
|
94
|
-
|
|
95
|
-
container.bind<string>({ key: 'APP_NAME' })
|
|
96
|
-
.toValue('MyApp');
|
|
42
|
+
**Scopes**
|
|
97
43
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return new DatabaseConnection(config);
|
|
103
|
-
});
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
#### Class-based Provider
|
|
107
|
-
|
|
108
|
-
For complex creation logic, implement the `IProvider<T>` interface:
|
|
109
|
-
|
|
110
|
-
```typescript
|
|
111
|
-
import { IProvider, Container } from '@venizia/ignis-inversion';
|
|
112
|
-
|
|
113
|
-
class DatabaseConnectionProvider implements IProvider<DatabaseConnection> {
|
|
114
|
-
value(container: Container): DatabaseConnection {
|
|
115
|
-
const config = container.get<Config>({ key: 'config.database' });
|
|
116
|
-
return new DatabaseConnection(config);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
container.bind<DatabaseConnection>({ key: 'db.connection' })
|
|
121
|
-
.toProvider(DatabaseConnectionProvider);
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
When `toProvider` receives a class with a `value()` method on its prototype, the container instantiates the class (with full DI support) and then calls `value(container)` to produce the final value.
|
|
125
|
-
|
|
126
|
-
#### Fluent Chaining
|
|
127
|
-
|
|
128
|
-
All `Binding` setter methods return `this` for chaining:
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
container.bind<CacheService>({ key: 'services.CacheService' })
|
|
132
|
-
.toClass(CacheService)
|
|
133
|
-
.setScope(BindingScopes.SINGLETON)
|
|
134
|
-
.setTags('infrastructure', 'cache');
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
#### Static Factory
|
|
138
|
-
|
|
139
|
-
`Binding` also exposes a static factory for creating bindings outside a container:
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
import { Binding, BindingScopes } from '@venizia/ignis-inversion';
|
|
44
|
+
| Scope | Constant | Behavior |
|
|
45
|
+
|-------|----------|----------|
|
|
46
|
+
| Transient | `BindingScopes.TRANSIENT` | New instance on every resolution (default) |
|
|
47
|
+
| Singleton | `BindingScopes.SINGLETON` | Cached on the `Binding` after first resolution |
|
|
143
48
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}).toValue({ restOptions: { path: '/health' } });
|
|
49
|
+
> [!IMPORTANT]
|
|
50
|
+
> Singleton caching lives on the `Binding` object, not the container. Rebinding a key creates a fresh `Binding` with its own cache; a `Binding` reference you hold onto keeps its own cache independent of `container.clear()`/`reset()` on a different `Binding` for the same key.
|
|
147
51
|
|
|
148
|
-
|
|
149
|
-
container.set({ binding });
|
|
150
|
-
```
|
|
52
|
+
Property-injected classes only get their `@inject` properties populated when built through the container (`container.resolve()`/`instantiate()`) - `new MyClass()` leaves them `undefined`. The [Full reference](/extensions/helpers/inversion/reference) covers `MetadataRegistry`, `gets()`, key formats, `IProvider`, and every error message in detail.
|
|
151
53
|
|
|
152
|
-
|
|
54
|
+
## Common tasks
|
|
153
55
|
|
|
154
|
-
|
|
56
|
+
### Bind a class with constructor injection
|
|
155
57
|
|
|
156
58
|
```typescript
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
@injectable({ scope: BindingScopes.SINGLETON })
|
|
160
|
-
class UserService {
|
|
59
|
+
class OrderService {
|
|
161
60
|
constructor(
|
|
162
|
-
@inject({ key: 'repositories.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
@inject({ key: 'services.Logger', isOptional: true })
|
|
166
|
-
private logger?: Logger,
|
|
61
|
+
@inject({ key: 'repositories.OrderRepository' }) private orderRepository: OrderRepository,
|
|
62
|
+
@inject({ key: 'services.Logger', isOptional: true }) private logger?: Logger,
|
|
167
63
|
) {}
|
|
168
64
|
}
|
|
169
65
|
```
|
|
170
66
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
> [!IMPORTANT]
|
|
174
|
-
> Every constructor parameter of a container-instantiated class must carry `@inject`. Mixing decorated and undecorated parameters is refused: an undecorated parameter leaves a hole in the index-keyed metadata array, and there is no channel through which the container could supply it anyway. `instantiate()` throws `[ClassName] Constructor parameter N has no @inject | Every parameter of a container-instantiated class must be decorated - the container cannot supply an undecorated one`.
|
|
175
|
-
|
|
176
|
-
### Property Injection
|
|
67
|
+
### Bind a value or a provider
|
|
177
68
|
|
|
178
69
|
```typescript
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
@injectable({})
|
|
182
|
-
class UserService {
|
|
183
|
-
@inject({ key: 'repositories.UserRepository' })
|
|
184
|
-
private userRepository: UserRepository;
|
|
70
|
+
container.bind<string>({ key: 'APP_NAME' }).toValue('MyApp');
|
|
185
71
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
72
|
+
container.bind<DatabaseConnection>({ key: 'db.connection' })
|
|
73
|
+
.toProvider((container) => {
|
|
74
|
+
const config = container.get<Config>({ key: 'config.database' });
|
|
75
|
+
return new DatabaseConnection(config);
|
|
76
|
+
});
|
|
189
77
|
```
|
|
190
78
|
|
|
191
|
-
|
|
192
|
-
> Property-injected classes must be instantiated through the container (`container.resolve()` or `container.instantiate()`). Using `new MyClass()` directly will leave `@inject` properties as `undefined`.
|
|
193
|
-
|
|
194
|
-
The instantiation algorithm is two-phase:
|
|
195
|
-
1. **Constructor injection** -- reads `@inject` metadata on the constructor by parameter index (no sort - the metadata is already index-keyed), resolves from container
|
|
196
|
-
2. **Property injection** -- reads property metadata, resolves and assigns each dependency to the instance
|
|
197
|
-
|
|
198
|
-
### Scopes (Singleton / Transient)
|
|
199
|
-
|
|
200
|
-
| Scope | Constant | Behavior |
|
|
201
|
-
|-------|----------|----------|
|
|
202
|
-
| Transient | `BindingScopes.TRANSIENT` | New instance every resolution (default) |
|
|
203
|
-
| Singleton | `BindingScopes.SINGLETON` | Cached after first resolution, reused thereafter |
|
|
79
|
+
### Set the scope
|
|
204
80
|
|
|
205
81
|
```typescript
|
|
206
|
-
import { BindingScopes } from '@venizia/ignis-inversion';
|
|
207
|
-
|
|
208
|
-
// Singleton -- one instance shared across all resolutions
|
|
209
82
|
container.bind({ key: 'services.CacheService' })
|
|
210
83
|
.toClass(CacheService)
|
|
211
|
-
.setScope(BindingScopes.SINGLETON);
|
|
212
|
-
|
|
213
|
-
// Transient (default) -- new instance every time
|
|
214
|
-
container.bind({ key: 'services.RequestHandler' })
|
|
215
|
-
.toClass(RequestHandler)
|
|
216
|
-
.setScope(BindingScopes.TRANSIENT);
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
> [!IMPORTANT]
|
|
220
|
-
> Singleton caching is per-`Binding` object, not per-Container. If you rebind the same key, the old `Binding` retains its cache independently.
|
|
221
|
-
|
|
222
|
-
#### Cache Management
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// Clear all singleton caches (bindings stay registered)
|
|
226
|
-
container.clear();
|
|
227
|
-
|
|
228
|
-
// Remove all bindings entirely (full reset)
|
|
229
|
-
container.reset();
|
|
230
|
-
|
|
231
|
-
// Clear cache for a single binding
|
|
232
|
-
const binding = container.getBinding({ key: 'services.CacheService' });
|
|
233
|
-
binding?.clearCache();
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
### Namespaces and Tags
|
|
237
|
-
|
|
238
|
-
Bindings with namespaced keys (e.g., `services.UserService`) are automatically tagged with the namespace portion (`services`). You can also add custom tags manually.
|
|
239
|
-
|
|
240
|
-
```typescript
|
|
241
|
-
container.bind({ key: 'workers.EmailWorker' })
|
|
242
|
-
.toClass(EmailWorker)
|
|
243
|
-
.setTags('background', 'email');
|
|
244
|
-
// This binding now has tags: ['workers', 'background', 'email']
|
|
245
|
-
|
|
246
|
-
// Find all bindings tagged 'services'
|
|
247
|
-
const serviceBindings = container.findByTag({ tag: 'services' });
|
|
248
|
-
|
|
249
|
-
// Exclude specific keys
|
|
250
|
-
const filtered = container.findByTag({
|
|
251
|
-
tag: 'services',
|
|
252
|
-
exclude: ['services.InternalService'],
|
|
253
|
-
});
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
#### Building Namespaced Keys
|
|
257
|
-
|
|
258
|
-
```typescript
|
|
259
|
-
import { BindingKeys } from '@venizia/ignis-inversion';
|
|
260
|
-
|
|
261
|
-
BindingKeys.build({ namespace: 'services', key: 'UserService' });
|
|
262
|
-
// => 'services.UserService'
|
|
263
|
-
|
|
264
|
-
// The key parameter is required; an empty key throws an error
|
|
265
|
-
BindingKeys.build({ namespace: '', key: 'UserService' });
|
|
266
|
-
// => 'UserService'
|
|
84
|
+
.setScope(BindingScopes.SINGLETON); // default is TRANSIENT if omitted
|
|
267
85
|
```
|
|
268
86
|
|
|
269
|
-
###
|
|
270
|
-
|
|
271
|
-
The `get`, `getBinding`, and `gets` methods accept three key formats:
|
|
272
|
-
|
|
273
|
-
```typescript
|
|
274
|
-
// String key
|
|
275
|
-
container.get<UserService>({ key: 'services.UserService' });
|
|
276
|
-
|
|
277
|
-
// Symbol key
|
|
278
|
-
container.get<UserService>({ key: Symbol.for('services.UserService') });
|
|
279
|
-
|
|
280
|
-
// Namespaced object (built via BindingKeys.build internally)
|
|
281
|
-
container.get<UserService>({ key: { namespace: 'services', key: 'UserService' } });
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### Optional Dependencies
|
|
285
|
-
|
|
286
|
-
```typescript
|
|
287
|
-
// Returns undefined instead of throwing if not bound
|
|
288
|
-
const maybeSvc = container.get<MyService>({
|
|
289
|
-
key: 'services.Optional',
|
|
290
|
-
isOptional: true,
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
// In decorators
|
|
294
|
-
@inject({ key: 'services.Logger', isOptional: true })
|
|
295
|
-
private logger?: Logger;
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
### Resolving Multiple Dependencies
|
|
299
|
-
|
|
300
|
-
```typescript
|
|
301
|
-
const [svcA, svcB] = container.gets<[ServiceA, ServiceB]>({
|
|
302
|
-
bindings: [
|
|
303
|
-
{ key: 'services.ServiceA' },
|
|
304
|
-
{ key: 'services.ServiceB', isOptional: true },
|
|
305
|
-
],
|
|
306
|
-
});
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
> [!NOTE]
|
|
310
|
-
> `gets()` internally calls `get()` with `isOptional: true` for each entry. Unresolved bindings return `undefined` rather than throwing.
|
|
311
|
-
|
|
312
|
-
### Instantiate Without Binding
|
|
313
|
-
|
|
314
|
-
```typescript
|
|
315
|
-
// Create an instance with full DI resolution but don't register it
|
|
316
|
-
const instance = container.resolve<MyClass>(MyClass);
|
|
317
|
-
// or equivalently:
|
|
318
|
-
const instance2 = container.instantiate<MyClass>(MyClass);
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
Both methods perform the same two-phase instantiation (constructor injection, then property injection). `resolve()` is an alias for `instantiate()`.
|
|
322
|
-
|
|
323
|
-
### Checking and Removing Bindings
|
|
87
|
+
### Inject into a property instead of the constructor
|
|
324
88
|
|
|
325
89
|
```typescript
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
// Remove a binding
|
|
330
|
-
container.unbind({ key: 'services.UserService' }); // returns true if removed, false if not found
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
### MetadataRegistry
|
|
334
|
-
|
|
335
|
-
The `MetadataRegistry` is a singleton that stores all decorator metadata using `reflect-metadata`. Both `@inject` and `@injectable` delegate to it. You typically will not interact with the registry directly.
|
|
336
|
-
|
|
337
|
-
```typescript
|
|
338
|
-
import { MetadataKeys, metadataRegistry } from '@venizia/ignis-inversion';
|
|
339
|
-
|
|
340
|
-
// Well-known metadata keys
|
|
341
|
-
MetadataKeys.PROPERTIES // Symbol.for('ignis:properties')
|
|
342
|
-
MetadataKeys.INJECT // Symbol.for('ignis:inject')
|
|
343
|
-
MetadataKeys.INJECTABLE // Symbol.for('ignis:injectable')
|
|
344
|
-
|
|
345
|
-
// Access via container
|
|
346
|
-
const registry = container.getMetadataRegistry();
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
The registry also supports generic metadata operations for storing arbitrary metadata on any object:
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
metadataRegistry.define({ target: myObj, key: 'custom:flag', value: true });
|
|
353
|
-
metadataRegistry.get({ target: myObj, key: 'custom:flag' }); // true
|
|
354
|
-
metadataRegistry.has({ target: myObj, key: 'custom:flag' }); // true
|
|
355
|
-
metadataRegistry.delete({ target: myObj, key: 'custom:flag' }); // true
|
|
356
|
-
```
|
|
357
|
-
|
|
358
|
-
### @injectable Decorator
|
|
359
|
-
|
|
360
|
-
Marks a class with DI metadata (scope and tags). Used by the framework layer to configure bindings automatically.
|
|
361
|
-
|
|
362
|
-
```typescript
|
|
363
|
-
@injectable({
|
|
364
|
-
scope: BindingScopes.SINGLETON,
|
|
365
|
-
tags: { category: 'infrastructure' },
|
|
366
|
-
})
|
|
367
|
-
class CacheService {
|
|
368
|
-
// ...
|
|
90
|
+
class UserService {
|
|
91
|
+
@inject({ key: 'repositories.UserRepository' })
|
|
92
|
+
private userRepository: UserRepository;
|
|
369
93
|
}
|
|
370
94
|
```
|
|
371
95
|
|
|
372
|
-
###
|
|
373
|
-
|
|
374
|
-
#### ApplicationError and getError
|
|
375
|
-
|
|
376
|
-
Error factory used internally and available for consumers:
|
|
377
|
-
|
|
378
|
-
```typescript
|
|
379
|
-
import { ApplicationError, getError, ErrorSchema } from '@venizia/ignis-inversion';
|
|
380
|
-
|
|
381
|
-
// Factory function
|
|
382
|
-
throw getError({ message: 'Something failed', statusCode: 500, messageCode: 'ERR_INTERNAL' });
|
|
383
|
-
|
|
384
|
-
// Direct construction (defaults to statusCode 400)
|
|
385
|
-
throw new ApplicationError({ message: 'Not found', statusCode: 404 });
|
|
386
|
-
|
|
387
|
-
// Zod schema for validation
|
|
388
|
-
ErrorSchema.parse({ message: 'test', statusCode: 400 });
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
#### Logger
|
|
96
|
+
### Resolve an optional dependency
|
|
392
97
|
|
|
393
|
-
|
|
98
|
+
`isOptional: true` returns `undefined` instead of throwing when the key is unbound - on the constructor and via `container.get()`. `gets()` resolves several keys at once, always treating each as optional.
|
|
394
99
|
|
|
395
100
|
```typescript
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
Logger.info('Server started on port %d', 3000);
|
|
399
|
-
Logger.warn('Deprecation warning');
|
|
400
|
-
Logger.error('Connection failed: %s', err.message);
|
|
401
|
-
Logger.debug('Resolved binding: %s', key); // Only prints when DEBUG env var is set
|
|
101
|
+
const maybeService = container.get<MyService>({ key: 'services.Optional', isOptional: true });
|
|
402
102
|
```
|
|
403
103
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
### Container
|
|
407
|
-
|
|
408
|
-
| Method | Signature | Description |
|
|
409
|
-
|--------|-----------|-------------|
|
|
410
|
-
| `bind` | `bind<T>(opts: { key: string \| symbol }): Binding<T>` | Create and register a new binding |
|
|
411
|
-
| `get` | `get<T>(opts: { key: string \| symbol \| { namespace, key }, isOptional?: boolean }): T` | Resolve a dependency by key; throws if not found and `isOptional` is `false` |
|
|
412
|
-
| `gets` | `gets<T>(opts: { bindings: Array<{ key, isOptional? }> }): T[]` | Resolve multiple dependencies at once (all treated as optional) |
|
|
413
|
-
| `getBinding` | `getBinding<T>(opts: { key: string \| symbol \| { namespace, key } }): Binding<T> \| undefined` | Retrieve the raw `Binding` without resolving |
|
|
414
|
-
| `set` | `set<T>(opts: { binding: Binding<T> }): void` | Register an externally-created binding |
|
|
415
|
-
| `isBound` | `isBound(opts: { key: string \| symbol }): boolean` | Check if a key is registered |
|
|
416
|
-
| `unbind` | `unbind(opts: { key: string \| symbol }): boolean` | Remove a binding; returns `true` if removed |
|
|
417
|
-
| `resolve` | `resolve<T>(cls: TClass<T>): T` | Alias for `instantiate` |
|
|
418
|
-
| `instantiate` | `instantiate<T>(cls: TClass<T>): T` | Create instance with full DI (constructor + property injection) |
|
|
419
|
-
| `findByTag` | `findByTag<T>(opts: { tag: string, exclude?: string[] \| Set<string> }): Binding<T>[]` | Find all bindings matching a tag, optionally excluding keys |
|
|
420
|
-
| `clear` | `clear(): void` | Clear all singleton caches (bindings remain) |
|
|
421
|
-
| `reset` | `reset(): void` | Remove all bindings entirely |
|
|
422
|
-
| `getMetadataRegistry` | `getMetadataRegistry(): MetadataRegistry` | Access the shared MetadataRegistry singleton |
|
|
423
|
-
|
|
424
|
-
### Binding
|
|
425
|
-
|
|
426
|
-
| Method | Signature | Description |
|
|
427
|
-
|--------|-----------|-------------|
|
|
428
|
-
| `toClass` | `toClass(value: TClass<T>): this` | Container instantiates the class with DI |
|
|
429
|
-
| `toValue` | `toValue(value: T): this` | Return value directly |
|
|
430
|
-
| `toProvider` | `toProvider(value: ((container) => T) \| TClass<IProvider<T>>): this` | Factory function or `IProvider` class |
|
|
431
|
-
| `setScope` | `setScope(scope: TBindingScope): this` | Set to `'singleton'` or `'transient'` (default) |
|
|
432
|
-
| `setTags` | `setTags(...tags: string[]): this` | Add string tags (namespace auto-tagged from key) |
|
|
433
|
-
| `hasTag` | `hasTag(tag: string): boolean` | Check if binding has a specific tag |
|
|
434
|
-
| `getTags` | `getTags(): string[]` | Get all tags as array |
|
|
435
|
-
| `getScope` | `getScope(): TBindingScope` | Get current scope |
|
|
436
|
-
| `getValue` | `getValue(container?: Container): T` | Resolve the bound value (respects scope caching) |
|
|
437
|
-
| `getBindingMeta` | `getBindingMeta(opts: { type: TBindingValueType }): any` | Get raw resolver value; throws if type does not match |
|
|
438
|
-
| `clearCache` | `clearCache(): void` | Clear singleton cache for this binding |
|
|
439
|
-
| `bind` (static) | `static bind<T>(opts: { key: string }): Binding<T>` | Static factory to create a Binding outside a container |
|
|
440
|
-
|
|
441
|
-
### MetadataRegistry
|
|
442
|
-
|
|
443
|
-
| Method | Signature | Description |
|
|
444
|
-
|--------|-----------|-------------|
|
|
445
|
-
| `define` | `define<Target, Value>(opts: { target: Target, key: string \| symbol, value: Value }): void` | Store arbitrary metadata on a target |
|
|
446
|
-
| `get` | `get<Target, Value>(opts: { target: Target, key: string \| symbol }): Value \| undefined` | Retrieve metadata by key |
|
|
447
|
-
| `has` | `has<Target>(opts: { target: Target, key: string \| symbol }): boolean` | Check if metadata exists |
|
|
448
|
-
| `delete` | `delete<Target>(opts: { target: Target, key: string \| symbol }): boolean` | Remove metadata by key |
|
|
449
|
-
| `getKeys` | `getKeys<Target>(opts: { target: Target }): (string \| symbol)[]` | List all metadata keys on a target |
|
|
450
|
-
| `getMethodNames` | `getMethodNames<T>(opts: { target: TClass<T> }): string[]` | List non-constructor method names on a class prototype |
|
|
451
|
-
| `clearMetadata` | `clearMetadata<T>(opts: { target: T }): void` | Remove all metadata from a target |
|
|
452
|
-
| `setInjectMetadata` | `setInjectMetadata<T>(opts: { target: T, index: number, metadata: IInjectMetadata }): void` | Store constructor `@inject` metadata at parameter index |
|
|
453
|
-
| `getInjectMetadata` | `getInjectMetadata<T>(opts: { target: T }): IInjectMetadata[] \| undefined` | Get all constructor injection metadata |
|
|
454
|
-
| `setPropertyMetadata` | `setPropertyMetadata<T>(opts: { target: T, propertyName: string \| symbol, metadata: IPropertyMetadata }): void` | Store property `@inject` metadata |
|
|
455
|
-
| `getPropertiesMetadata` | `getPropertiesMetadata<T>(opts: { target: T }): Map<string \| symbol, IPropertyMetadata> \| undefined` | Get all property injection metadata |
|
|
456
|
-
| `getPropertyMetadata` | `getPropertyMetadata<T>(opts: { target: T, propertyName: string \| symbol }): IPropertyMetadata \| undefined` | Get single property injection metadata |
|
|
457
|
-
| `setInjectableMetadata` | `setInjectableMetadata<T>(opts: { target: T, metadata: IInjectableMetadata }): void` | Store `@injectable` metadata |
|
|
458
|
-
| `getInjectableMetadata` | `getInjectableMetadata<T>(opts: { target: T }): IInjectableMetadata \| undefined` | Get `@injectable` metadata |
|
|
459
|
-
|
|
460
|
-
### Decorators
|
|
461
|
-
|
|
462
|
-
| Decorator | Signature | Description |
|
|
463
|
-
|-----------|-----------|-------------|
|
|
464
|
-
| `@inject` | `inject(opts: { key: string \| symbol, isOptional?: boolean, registry?: MetadataRegistry })` | Marks a constructor parameter or property for dependency injection |
|
|
465
|
-
| `@injectable` | `injectable(metadata: { scope?: TBindingScope, tags?: Record<string, any> }, registry?: MetadataRegistry)` | Marks a class with DI metadata (scope and tags) |
|
|
466
|
-
|
|
467
|
-
### Constants
|
|
468
|
-
|
|
469
|
-
| Constant | Values | Description |
|
|
470
|
-
|----------|--------|-------------|
|
|
471
|
-
| `BindingScopes.SINGLETON` | `'singleton'` | Cached after first resolution |
|
|
472
|
-
| `BindingScopes.TRANSIENT` | `'transient'` | New instance each resolution |
|
|
473
|
-
| `BindingValueTypes.CLASS` | `'class'` | Container instantiates with DI |
|
|
474
|
-
| `BindingValueTypes.VALUE` | `'value'` | Direct value return |
|
|
475
|
-
| `BindingValueTypes.PROVIDER` | `'provider'` | Factory function or IProvider class |
|
|
476
|
-
| `MetadataKeys.PROPERTIES` | `Symbol.for('ignis:properties')` | Property injection metadata key |
|
|
477
|
-
| `MetadataKeys.INJECT` | `Symbol.for('ignis:inject')` | Constructor injection metadata key |
|
|
478
|
-
| `MetadataKeys.INJECTABLE` | `Symbol.for('ignis:injectable')` | Injectable class metadata key |
|
|
479
|
-
|
|
480
|
-
### Exported Types
|
|
104
|
+
### Instantiate a class without registering it
|
|
481
105
|
|
|
482
106
|
```typescript
|
|
483
|
-
|
|
484
|
-
type ValueOrPromise<T> = T | Promise<T>;
|
|
485
|
-
type ValueOf<T> = T[keyof T];
|
|
486
|
-
type TConstructor<T> = new (...args: any[]) => T;
|
|
487
|
-
type TAbstractConstructor<T> = abstract new (...args: any[]) => T;
|
|
488
|
-
type TClass<T> = TConstructor<T> & { [property: string]: any };
|
|
489
|
-
type TConstValue<T extends TClass<any>> = Extract<ValueOf<T>, string | number>;
|
|
490
|
-
type TBindingScope = 'singleton' | 'transient';
|
|
491
|
-
type TBindingValueType = 'class' | 'value' | 'provider';
|
|
492
|
-
|
|
493
|
-
interface IProvider<T> {
|
|
494
|
-
value(container: Container): T;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
interface IInjectMetadata {
|
|
498
|
-
key: string | symbol;
|
|
499
|
-
index: number;
|
|
500
|
-
isOptional?: boolean;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
interface IPropertyMetadata {
|
|
504
|
-
bindingKey: string | symbol;
|
|
505
|
-
isOptional?: boolean;
|
|
506
|
-
[key: string]: any;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
interface IInjectableMetadata {
|
|
510
|
-
scope?: TBindingScope;
|
|
511
|
-
tags?: Record<string, any>;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// Type guards
|
|
515
|
-
function isClass<T>(target: any): target is TClass<T>;
|
|
516
|
-
function isClassProvider<T>(target: any): target is TClass<IProvider<T>>;
|
|
107
|
+
const instance = container.resolve<MyClass>(MyClass); // full DI, not bound to a key
|
|
517
108
|
```
|
|
518
109
|
|
|
519
|
-
##
|
|
520
|
-
|
|
521
|
-
### "Binding key: X is not bounded in context!"
|
|
522
|
-
|
|
523
|
-
**Cause:** The dependency was never registered with the container, or the key string does not match exactly.
|
|
524
|
-
|
|
525
|
-
**Fix:**
|
|
526
|
-
1. Verify the binding exists: `container.isBound({ key: 'services.UserService' })`.
|
|
527
|
-
2. Check for typos in the key passed to `@inject({ key: '...' })` vs the key used in `container.bind({ key: '...' })`.
|
|
528
|
-
3. If the dependency is optional, use `@inject({ key: '...', isOptional: true })` or `container.get({ key: '...', isOptional: true })`.
|
|
529
|
-
|
|
530
|
-
### "[getValue] Invalid context/container to instantiate class"
|
|
531
|
-
|
|
532
|
-
**Cause:** A `Binding` configured with `toClass()` was resolved without a `Container` reference. This happens when calling `binding.getValue()` directly without passing a container.
|
|
533
|
-
|
|
534
|
-
**Fix:** Always resolve class bindings through the container via `container.get({ key })` rather than calling `binding.getValue()` without arguments.
|
|
535
|
-
|
|
536
|
-
### "[getValue] Invalid context/container to get provider value"
|
|
537
|
-
|
|
538
|
-
**Cause:** A `Binding` configured with `toProvider()` was resolved without a `Container` reference.
|
|
539
|
-
|
|
540
|
-
**Fix:** Same as above -- resolve provider bindings through the container via `container.get({ key })`.
|
|
541
|
-
|
|
542
|
-
### "[getBindingMeta] Invalid resolver type"
|
|
543
|
-
|
|
544
|
-
**Cause:** Called `getBindingMeta({ type })` with a type that does not match the binding's actual resolver type (e.g., asking for `'class'` on a value binding).
|
|
545
|
-
|
|
546
|
-
**Fix:** Ensure the `type` parameter matches the binding's resolver. Check what was used: `toClass()` = `'class'`, `toValue()` = `'value'`, `toProvider()` = `'provider'`.
|
|
547
|
-
|
|
548
|
-
### "[getBinding] Invalid binding key type"
|
|
549
|
-
|
|
550
|
-
**Cause:** The key passed to `getBinding()` is not a `string`, `symbol`, or `{ namespace, key }` object.
|
|
551
|
-
|
|
552
|
-
**Fix:** Use one of the three supported key formats: a string, a symbol, or an object with `namespace` and `key` properties.
|
|
553
|
-
|
|
554
|
-
### "[BindingKeys][build] Invalid key to build"
|
|
555
|
-
|
|
556
|
-
**Cause:** Called `BindingKeys.build()` with an empty `key` value.
|
|
557
|
-
|
|
558
|
-
**Fix:** Provide a non-empty `key` string: `BindingKeys.build({ namespace: 'services', key: 'UserService' })`.
|
|
559
|
-
|
|
560
|
-
### "[ClassName] Constructor parameter N has no @inject"
|
|
561
|
-
|
|
562
|
-
**Cause:** A container-instantiated class has a constructor with a mix of decorated and undecorated parameters. `@inject` stores its metadata at the parameter's index, so an undecorated parameter leaves a hole in that index-keyed array; there is no channel through which the container could supply it anyway. `instantiate()` refuses the shape by name and index rather than passing `undefined`.
|
|
563
|
-
|
|
564
|
-
**Fix:** Decorate every constructor parameter of the class with `@inject`. There is no partial-injection escape hatch - if a value does not come from the container (e.g. a plain `scope: string`), pass it through a factory/provider instead of a bare constructor parameter, or have the subclass forward it via its own `@inject`-decorated parameter.
|
|
565
|
-
|
|
566
|
-
### "@inject decorator can only be used on class properties or constructor parameters"
|
|
567
|
-
|
|
568
|
-
**Cause:** The `@inject` decorator was applied to something other than a class property or constructor parameter.
|
|
569
|
-
|
|
570
|
-
**Fix:** Only use `@inject` on constructor parameters or class properties.
|
|
571
|
-
|
|
572
|
-
### "Property injection returns undefined"
|
|
573
|
-
|
|
574
|
-
**Cause:** The class was instantiated with `new MyClass()` directly instead of going through the container.
|
|
575
|
-
|
|
576
|
-
**Fix:** Always use `container.resolve(MyClass)` or `container.instantiate(MyClass)` to create instances. Only the container reads `@inject` metadata and populates injected properties.
|
|
577
|
-
|
|
578
|
-
### "getInjectMetadata returns undefined"
|
|
579
|
-
|
|
580
|
-
**Cause:** `reflect-metadata` was not imported before decorators were evaluated, or `experimentalDecorators` / `emitDecoratorMetadata` are not enabled in `tsconfig.json`.
|
|
581
|
-
|
|
582
|
-
**Fix:**
|
|
583
|
-
1. Ensure `import 'reflect-metadata'` is at the top of your entry point (or rely on `@venizia/ignis-inversion` which imports it automatically).
|
|
584
|
-
2. Verify your `tsconfig.json` includes:
|
|
585
|
-
```json
|
|
586
|
-
{
|
|
587
|
-
"compilerOptions": {
|
|
588
|
-
"experimentalDecorators": true,
|
|
589
|
-
"emitDecoratorMetadata": true
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
```
|
|
593
|
-
|
|
594
|
-
### "Singleton returns stale instance after rebinding"
|
|
595
|
-
|
|
596
|
-
**Cause:** Singleton caching is per-`Binding` object. If you hold a direct reference to an old `Binding` (e.g., from `getBinding()`), its cache is independent of the container.
|
|
597
|
-
|
|
598
|
-
**Fix:**
|
|
599
|
-
1. Always resolve via `container.get()` rather than caching `Binding` references.
|
|
600
|
-
2. Call `container.clear()` to clear all singleton caches without removing bindings.
|
|
601
|
-
3. Call `container.reset()` to remove all bindings entirely.
|
|
602
|
-
|
|
603
|
-
## See Also
|
|
604
|
-
|
|
605
|
-
- **Guides:**
|
|
606
|
-
- [Dependency Injection Guide](/guides/core-concepts/dependency-injection) - DI fundamentals
|
|
607
|
-
- [Application](/guides/core-concepts/application/) - Application extends Container
|
|
110
|
+
## See also
|
|
608
111
|
|
|
609
|
-
-
|
|
610
|
-
|
|
112
|
+
- [Full reference](/extensions/helpers/inversion/reference) - every method, `MetadataRegistry`, error message, and edge case
|
|
113
|
+
- [Dependency Injection Guide](/guides/core-concepts/dependency-injection) - DI fundamentals in the framework layer
|
|
114
|
+
- [Application](/guides/core-concepts/application/) - `Application` extends `Container`
|
|
115
|
+
- [Dependency Injection API](/references/base/dependency-injection) - the framework-layer DI reference
|
|
116
|
+
- [Helpers Overview](/extensions/helpers/) - all available helpers
|
|
117
|
+
- [Architectural Patterns](/best-practices/architectural-patterns) - DI patterns
|
|
611
118
|
|
|
612
|
-
|
|
613
|
-
- [Dependency Injection API](/references/base/dependency-injection) - Complete DI reference
|
|
119
|
+
**Files:**
|
|
614
120
|
|
|
615
|
-
-
|
|
616
|
-
|
|
121
|
+
- [`packages/inversion/src/modules/container/container.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/inversion/src/modules/container/container.ts) - `Container`, two-phase `instantiate()`
|
|
122
|
+
- [`packages/inversion/src/modules/container/base.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/inversion/src/modules/container/base.ts) - `BaseContainer`, binding storage
|
|
123
|
+
- [`packages/inversion/src/modules/binding/binding.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/inversion/src/modules/binding/binding.ts) - `Binding`
|
|
124
|
+
- [`packages/inversion/src/modules/metadata/injectors.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/inversion/src/modules/metadata/injectors.ts) - `@inject`
|
|
125
|
+
- [`packages/inversion/src/modules/registry/registry.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/inversion/src/modules/registry/registry.ts) - `MetadataRegistry`
|