katagami 1.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/LICENSE +21 -0
- package/README.de.md +438 -0
- package/README.es.md +386 -0
- package/README.fr.md +386 -0
- package/README.ja.md +438 -0
- package/README.ko.md +438 -0
- package/README.md +438 -0
- package/README.zh-CN.md +438 -0
- package/README.zh-TW.md +438 -0
- package/dist/container/index.d.ts +146 -0
- package/dist/error/index.d.ts +11 -0
- package/dist/index.cjs +264 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +232 -0
- package/dist/resolver/index.d.ts +68 -0
- package/dist/scope/index.d.ts +81 -0
- package/package.json +53 -0
package/README.es.md
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
[English](./README.md) | [日本語](./README.ja.md) | [한국어](./README.ko.md) | [繁體中文](./README.zh-TW.md) | [简体中文](./README.zh-CN.md) | [Español](./README.es.md) | [Deutsch](./README.de.md) | [Français](./README.fr.md)
|
|
2
|
+
|
|
3
|
+
# Katagami
|
|
4
|
+
|
|
5
|
+
Contenedor DI ligero para TypeScript con inferencia de tipos completa.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/katagami)
|
|
8
|
+
[](https://github.com/hiroiku/katagami/blob/master/LICENSE)
|
|
9
|
+
[](https://bundlephobia.com/package/katagami)
|
|
10
|
+
|
|
11
|
+
> El nombre proviene de 型紙 _(katagami)_ — papel de estarcido de precisión utilizado en el teñido tradicional japonés para transferir patrones exactos sobre la tela. Se superponen múltiples estarcidos para componer diseños intrincados, de la misma manera que los tipos se acumulan con cada llamada en la cadena de métodos. Un estarcido solo necesita papel y un pincel, sin maquinaria elaborada — del mismo modo, Katagami no requiere decoradores ni mecanismos de metadatos y funciona con cualquier herramienta de construcción sin configuración adicional. Y al igual que los estarcidos se adaptan a diferentes telas y técnicas, Katagami se adapta a TypeScript y JavaScript, tokens de clase y tokens PropertyKey — un enfoque híbrido para una DI estricta y componible.
|
|
12
|
+
|
|
13
|
+
## Características
|
|
14
|
+
|
|
15
|
+
| Característica | Descripción |
|
|
16
|
+
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| Inferencia de tipos completa | Los tipos se acumulan mediante encadenamiento de métodos; los tokens no registrados generan errores en tiempo de compilación |
|
|
18
|
+
| Tres ciclos de vida | Singleton, Transient y Scoped con contenedores hijos |
|
|
19
|
+
| Fábricas asíncronas | Las fábricas que retornan Promise son rastreadas automáticamente por el sistema de tipos |
|
|
20
|
+
| Detección de dependencias circulares | Mensajes de error claros con la ruta completa del ciclo |
|
|
21
|
+
| Soporte Disposable | TC39 Explicit Resource Management (`Symbol.dispose` / `Symbol.asyncDispose` / `await using`) |
|
|
22
|
+
| Prevención de dependencias cautivas | Las fábricas Singleton/Transient no pueden acceder a tokens Scoped; detectado en tiempo de compilación |
|
|
23
|
+
| Resolución opcional | `tryResolve` devuelve `undefined` para tokens no registrados en lugar de lanzar |
|
|
24
|
+
| Estrategia de tokens híbrida | Tokens de clase para seguridad de tipos estricta, tokens PropertyKey para flexibilidad |
|
|
25
|
+
| Mapa de tipos con interfaz | Pasa una interfaz a `createContainer<T>()` para registro independiente del orden |
|
|
26
|
+
| Cero dependencias | Sin decoradores, sin reflect-metadata, sin polyfills |
|
|
27
|
+
|
|
28
|
+
## Instalación
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install katagami
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Inicio rápido
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
import { createContainer } from 'katagami';
|
|
38
|
+
|
|
39
|
+
class Logger {
|
|
40
|
+
log(msg: string) {
|
|
41
|
+
console.log(msg);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class UserService {
|
|
46
|
+
constructor(private logger: Logger) {}
|
|
47
|
+
greet(name: string) {
|
|
48
|
+
this.logger.log(`Hello, ${name}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const container = createContainer()
|
|
53
|
+
.registerSingleton(Logger, () => new Logger())
|
|
54
|
+
.registerSingleton(UserService, r => new UserService(r.resolve(Logger)));
|
|
55
|
+
|
|
56
|
+
const userService = container.resolve(UserService);
|
|
57
|
+
// ^? UserService (inferencia completa)
|
|
58
|
+
userService.greet('world');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Por qué Katagami
|
|
62
|
+
|
|
63
|
+
La mayoría de los contenedores DI de TypeScript dependen de decoradores, reflect-metadata o tokens basados en cadenas de texto — cada uno con compromisos en compatibilidad de herramientas, seguridad de tipos o tamaño del paquete. Katagami adopta un enfoque diferente.
|
|
64
|
+
|
|
65
|
+
### Sin decoradores, sin reflect-metadata
|
|
66
|
+
|
|
67
|
+
La DI basada en decoradores requiere las opciones del compilador `experimentalDecorators` y `emitDecoratorMetadata`. Las herramientas de construcción modernas como esbuild y Vite (configuración por defecto) no soportan `emitDecoratorMetadata`, y la propuesta de decoradores estándar TC39 no incluye un equivalente para la emisión automática de metadatos de tipos. Katagami no depende de nada de esto — funciona con cualquier herramienta de construcción sin configuración adicional.
|
|
68
|
+
|
|
69
|
+
### Inferencia de tipos completa desde tokens de clase
|
|
70
|
+
|
|
71
|
+
La DI con tokens de cadena te obliga a mantener mapeos manuales de token a tipo. La coincidencia por nombre de parámetro se rompe con la minificación. Katagami usa clases directamente como tokens, así que `resolve` infiere automáticamente el tipo de retorno correcto — síncrono o `Promise` — sin anotaciones adicionales.
|
|
72
|
+
|
|
73
|
+
### Acumulación de tipos en cadena de métodos
|
|
74
|
+
|
|
75
|
+
Los tipos se acumulan con cada llamada a `register`. Dentro de una fábrica, el resolver solo acepta tokens que ya han sido registrados en ese punto de la cadena. Resolver un token no registrado es un error de compilación, no una sorpresa en tiempo de ejecución.
|
|
76
|
+
|
|
77
|
+
### Estrategia de tokens híbrida
|
|
78
|
+
|
|
79
|
+
Los tokens de clase te dan seguridad de tipos estricta y dependiente del orden a través del encadenamiento de métodos. Pero a veces quieres definir un conjunto de servicios por adelantado y registrarlos en cualquier orden. Pasa una interfaz a `createContainer<T>()` y usa tokens PropertyKey — el mapa de tipos se fija en el momento de la creación, así que el orden de registro no importa.
|
|
80
|
+
|
|
81
|
+
### Cero dependencias
|
|
82
|
+
|
|
83
|
+
Sin dependencias en tiempo de ejecución, sin polyfills. No necesitas añadir reflect-metadata (~50 KB sin minificar) a tu paquete.
|
|
84
|
+
|
|
85
|
+
## Guía
|
|
86
|
+
|
|
87
|
+
### Singleton y Transient
|
|
88
|
+
|
|
89
|
+
Singleton crea la instancia en el primer `resolve` y la almacena en caché. Transient crea una nueva instancia cada vez.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { createContainer } from 'katagami';
|
|
93
|
+
|
|
94
|
+
class Database {
|
|
95
|
+
constructor(public id = Math.random()) {}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
class RequestHandler {
|
|
99
|
+
constructor(public id = Math.random()) {}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const container = createContainer()
|
|
103
|
+
.registerSingleton(Database, () => new Database())
|
|
104
|
+
.registerTransient(RequestHandler, () => new RequestHandler());
|
|
105
|
+
|
|
106
|
+
// Singleton — siempre la misma instancia
|
|
107
|
+
container.resolve(Database) === container.resolve(Database); // true
|
|
108
|
+
|
|
109
|
+
// Transient — nueva instancia cada vez
|
|
110
|
+
container.resolve(RequestHandler) === container.resolve(RequestHandler); // false
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Ciclo de vida Scoped y contenedores hijos
|
|
114
|
+
|
|
115
|
+
Los registros Scoped se comportan como singletons dentro de un scope pero producen una instancia nueva en cada nuevo scope. Usa `createScope()` para crear un contenedor hijo. Los tokens Scoped no pueden resolverse desde el contenedor raíz.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { createContainer } from 'katagami';
|
|
119
|
+
|
|
120
|
+
class DbPool {
|
|
121
|
+
constructor(public name = 'main') {}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
class RequestContext {
|
|
125
|
+
constructor(public id = Math.random()) {}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const root = createContainer()
|
|
129
|
+
.registerSingleton(DbPool, () => new DbPool())
|
|
130
|
+
.registerScoped(RequestContext, () => new RequestContext());
|
|
131
|
+
|
|
132
|
+
// Crear un scope para cada petición
|
|
133
|
+
const scope1 = root.createScope();
|
|
134
|
+
const scope2 = root.createScope();
|
|
135
|
+
|
|
136
|
+
// Scoped — mismo dentro de un scope, diferente entre scopes
|
|
137
|
+
scope1.resolve(RequestContext) === scope1.resolve(RequestContext); // true
|
|
138
|
+
scope1.resolve(RequestContext) === scope2.resolve(RequestContext); // false
|
|
139
|
+
|
|
140
|
+
// Singleton — compartido entre todos los scopes
|
|
141
|
+
scope1.resolve(DbPool) === scope2.resolve(DbPool); // true
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Los scopes también pueden anidarse. Cada scope anidado tiene su propia caché de instancias Scoped mientras comparte singletons con su padre:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
const parentScope = root.createScope();
|
|
148
|
+
const childScope = parentScope.createScope();
|
|
149
|
+
|
|
150
|
+
// Cada scope anidado obtiene sus propias instancias Scoped
|
|
151
|
+
parentScope.resolve(RequestContext) === childScope.resolve(RequestContext); // false
|
|
152
|
+
|
|
153
|
+
// Los singletons siguen siendo compartidos
|
|
154
|
+
parentScope.resolve(DbPool) === childScope.resolve(DbPool); // true
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Fábricas asíncronas
|
|
158
|
+
|
|
159
|
+
Las fábricas que retornan `Promise` son rastreadas automáticamente por el sistema de tipos. Cuando resuelves un token asíncrono, el tipo de retorno es `Promise<V>` en lugar de `V`:
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import { createContainer } from 'katagami';
|
|
163
|
+
|
|
164
|
+
class Database {
|
|
165
|
+
constructor(public connected: boolean) {}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
class Logger {
|
|
169
|
+
log(msg: string) {
|
|
170
|
+
console.log(msg);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const container = createContainer()
|
|
175
|
+
.registerSingleton(Logger, () => new Logger())
|
|
176
|
+
.registerSingleton(Database, async () => {
|
|
177
|
+
await new Promise(r => setTimeout(r, 100)); // simular inicialización asíncrona
|
|
178
|
+
return new Database(true);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
const logger = container.resolve(Logger);
|
|
182
|
+
// ^? Logger
|
|
183
|
+
|
|
184
|
+
const db = await container.resolve(Database);
|
|
185
|
+
// ^? Promise<Database> (con await → Database)
|
|
186
|
+
db.connected; // true
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Las fábricas asíncronas pueden depender tanto de registros síncronos como asíncronos:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
const container = createContainer()
|
|
193
|
+
.registerSingleton(Logger, () => new Logger())
|
|
194
|
+
.registerSingleton(Database, async r => {
|
|
195
|
+
const logger = r.resolve(Logger); // síncrono → Logger
|
|
196
|
+
logger.log('Conectando...');
|
|
197
|
+
return new Database(true);
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Detección de dependencias circulares
|
|
202
|
+
|
|
203
|
+
Katagami rastrea qué tokens se están resolviendo actualmente. Si se encuentra una dependencia circular, se lanza un `ContainerError` con un mensaje claro que muestra la ruta completa del ciclo:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
import { createContainer } from 'katagami';
|
|
207
|
+
|
|
208
|
+
class ServiceA {
|
|
209
|
+
constructor(public b: ServiceB) {}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
class ServiceB {
|
|
213
|
+
constructor(public a: ServiceA) {}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const container = createContainer()
|
|
217
|
+
.registerSingleton(ServiceA, r => new ServiceA(r.resolve(ServiceB)))
|
|
218
|
+
.registerSingleton(ServiceB, r => new ServiceB(r.resolve(ServiceA)));
|
|
219
|
+
|
|
220
|
+
container.resolve(ServiceA);
|
|
221
|
+
// ContainerError: Circular dependency detected: ServiceA -> ServiceB -> ServiceA
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Los ciclos indirectos también son detectados:
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
ContainerError: Circular dependency detected: ServiceX -> ServiceY -> ServiceZ -> ServiceX
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Soporte Disposable
|
|
231
|
+
|
|
232
|
+
Tanto `Container` como `Scope` implementan `AsyncDisposable`. Al ser eliminados, las instancias gestionadas se recorren en orden inverso de creación (LIFO) y sus métodos `[Symbol.asyncDispose]()` o `[Symbol.dispose]()` se llaman automáticamente.
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import { createContainer } from 'katagami';
|
|
236
|
+
|
|
237
|
+
class Connection {
|
|
238
|
+
async [Symbol.asyncDispose]() {
|
|
239
|
+
console.log('Connection closed');
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Eliminación manual
|
|
244
|
+
const container = createContainer().registerSingleton(Connection, () => new Connection());
|
|
245
|
+
|
|
246
|
+
container.resolve(Connection);
|
|
247
|
+
await container[Symbol.asyncDispose]();
|
|
248
|
+
// => "Connection closed"
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Con `await using`, los scopes se eliminan automáticamente al final del bloque:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
const root = createContainer()
|
|
255
|
+
.registerSingleton(DbPool, () => new DbPool())
|
|
256
|
+
.registerScoped(Connection, () => new Connection());
|
|
257
|
+
|
|
258
|
+
{
|
|
259
|
+
await using scope = root.createScope();
|
|
260
|
+
const conn = scope.resolve(Connection);
|
|
261
|
+
// ... usar conn ...
|
|
262
|
+
} // el scope se elimina aquí — Connection se limpia, DbPool no
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
La eliminación del scope solo afecta a las instancias Scoped. Las instancias Singleton son propiedad del contenedor raíz y se eliminan cuando el propio contenedor es eliminado.
|
|
266
|
+
|
|
267
|
+
### Mapa de tipos con interfaz
|
|
268
|
+
|
|
269
|
+
Cuando pasas una interfaz a `createContainer<T>()`, los tokens PropertyKey obtienen sus tipos de la interfaz en lugar de acumularlos mediante encadenamiento. Esto significa que puedes registrar y resolver tokens en cualquier orden:
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
import { createContainer } from 'katagami';
|
|
273
|
+
|
|
274
|
+
class Logger {
|
|
275
|
+
log(msg: string) {
|
|
276
|
+
console.log(msg);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
interface Services {
|
|
281
|
+
logger: Logger;
|
|
282
|
+
greeting: string;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const container = createContainer<Services>()
|
|
286
|
+
// 'greeting' puede referenciar 'logger' aunque se registre después
|
|
287
|
+
.registerSingleton('greeting', r => {
|
|
288
|
+
r.resolve('logger').log('Construyendo greeting...');
|
|
289
|
+
return 'Hello!';
|
|
290
|
+
})
|
|
291
|
+
.registerSingleton('logger', () => new Logger());
|
|
292
|
+
|
|
293
|
+
const greeting = container.resolve('greeting');
|
|
294
|
+
// ^? string
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Estrategia de tokens híbrida
|
|
298
|
+
|
|
299
|
+
Puedes mezclar ambos enfoques — usa tokens de clase para seguridad de tipos dependiente del orden y tokens PropertyKey para flexibilidad independiente del orden:
|
|
300
|
+
|
|
301
|
+
```ts
|
|
302
|
+
const container = createContainer<Services>()
|
|
303
|
+
.registerSingleton(Logger, () => new Logger())
|
|
304
|
+
.registerSingleton('logger', () => new Logger())
|
|
305
|
+
.registerSingleton('greeting', r => {
|
|
306
|
+
r.resolve(Logger).log('Construyendo greeting...');
|
|
307
|
+
return 'Hello!';
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Prevención de dependencias cautivas
|
|
312
|
+
|
|
313
|
+
Una "dependencia cautiva" ocurre cuando un servicio de larga vida (singleton o transient) captura un servicio de corta vida (scoped), manteniéndolo vivo más allá de su scope previsto. Katagami previene esto en tiempo de compilación — las fábricas singleton y transient solo reciben un resolver limitado a tokens no Scoped:
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
import { createContainer } from 'katagami';
|
|
317
|
+
|
|
318
|
+
class DbPool {}
|
|
319
|
+
class RequestContext {}
|
|
320
|
+
|
|
321
|
+
const container = createContainer()
|
|
322
|
+
.registerScoped(RequestContext, () => new RequestContext())
|
|
323
|
+
// @ts-expect-error — la fábrica singleton no puede resolver tokens Scoped
|
|
324
|
+
.registerSingleton(DbPool, r => new DbPool(r.resolve(RequestContext)));
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Las fábricas Scoped, por otro lado, pueden resolver tanto tokens Scoped como no Scoped:
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
const container = createContainer()
|
|
331
|
+
.registerSingleton(DbPool, () => new DbPool())
|
|
332
|
+
.registerScoped(RequestContext, r => {
|
|
333
|
+
r.resolve(DbPool); // OK — la fábrica Scoped puede resolver tokens Singleton
|
|
334
|
+
return new RequestContext();
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## API
|
|
339
|
+
|
|
340
|
+
### `createContainer<T, ScopedT>()`
|
|
341
|
+
|
|
342
|
+
Crea un nuevo contenedor DI. Pasa una interfaz como `T` para definir el mapa de tipos para tokens PropertyKey. Pasa `ScopedT` para definir un mapa de tipos separado para tokens PropertyKey Scoped (independiente del orden, igual que `T`).
|
|
343
|
+
|
|
344
|
+
### `container.registerSingleton(token, factory)`
|
|
345
|
+
|
|
346
|
+
Registra una fábrica como singleton. La instancia se crea en el primer `resolve` y se almacena en caché. Retorna el contenedor para encadenamiento de métodos.
|
|
347
|
+
|
|
348
|
+
### `container.registerTransient(token, factory)`
|
|
349
|
+
|
|
350
|
+
Registra una fábrica como transient. Se crea una nueva instancia en cada `resolve`. Retorna el contenedor para encadenamiento de métodos.
|
|
351
|
+
|
|
352
|
+
### `container.registerScoped(token, factory)`
|
|
353
|
+
|
|
354
|
+
Registra una fábrica como scoped. Dentro de un scope, la instancia se crea en el primer `resolve` y se almacena en caché para ese scope. Cada scope mantiene su propia caché. Los tokens Scoped no pueden resolverse desde el contenedor raíz. Retorna el contenedor para encadenamiento de métodos.
|
|
355
|
+
|
|
356
|
+
### `container.resolve(token)`
|
|
357
|
+
|
|
358
|
+
Resuelve y retorna la instancia para el token dado. Lanza `ContainerError` si el token no está registrado o si se detecta una dependencia circular.
|
|
359
|
+
|
|
360
|
+
### `container.tryResolve(token)` / `scope.tryResolve(token)`
|
|
361
|
+
|
|
362
|
+
Intenta resolver la instancia para el token dado. Devuelve `undefined` si el token no está registrado, en lugar de lanzar. Aún lanza `ContainerError` para dependencias circulares u operaciones en contenedores/scopes eliminados.
|
|
363
|
+
|
|
364
|
+
### `container.createScope()`
|
|
365
|
+
|
|
366
|
+
Crea un nuevo `Scope` (contenedor hijo). El scope hereda todos los registros del padre. Las instancias Singleton se comparten con el padre, mientras que las instancias Scoped son locales al scope.
|
|
367
|
+
|
|
368
|
+
### `Scope`
|
|
369
|
+
|
|
370
|
+
Un contenedor hijo con scope creado por `createScope()`. Proporciona `resolve(token)`, `tryResolve(token)`, `createScope()` (para scopes anidados) y `[Symbol.asyncDispose]()`.
|
|
371
|
+
|
|
372
|
+
### `container[Symbol.asyncDispose]()` / `scope[Symbol.asyncDispose]()`
|
|
373
|
+
|
|
374
|
+
Elimina todas las instancias gestionadas en orden inverso de creación (LIFO). Llama a `[Symbol.asyncDispose]()` o `[Symbol.dispose]()` en cada instancia que los implemente. Idempotente — las llamadas posteriores no hacen nada. Después de la eliminación, `resolve()` y `createScope()` lanzarán `ContainerError`.
|
|
375
|
+
|
|
376
|
+
### `ContainerError`
|
|
377
|
+
|
|
378
|
+
Clase de error lanzada para fallos del contenedor como resolver un token no registrado, dependencias circulares u operaciones en un contenedor/scope eliminado.
|
|
379
|
+
|
|
380
|
+
### `Resolver`
|
|
381
|
+
|
|
382
|
+
Exportación de tipo que representa el resolver pasado a los callbacks de fábrica. Útil cuando necesitas tipar una función que acepta un parámetro resolver.
|
|
383
|
+
|
|
384
|
+
## Licencia
|
|
385
|
+
|
|
386
|
+
MIT
|