@zanobijs/core 1.2.0 → 2.0.0-beta.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.
Files changed (54) hide show
  1. package/lib/cjs/exceptions/circularModuleImport.exception.js +21 -0
  2. package/{exceptions → lib/cjs/exceptions}/constant.message.js +10 -6
  3. package/{exceptions → lib/cjs/exceptions}/invalid.module.exception.js +8 -7
  4. package/lib/cjs/exceptions/invalidProvider.module.exception.js +20 -0
  5. package/lib/cjs/exceptions/missingInjectToken.exception.js +20 -0
  6. package/{exceptions → lib/cjs/exceptions}/resolution.exception.js +11 -10
  7. package/lib/cjs/factory.js +213 -0
  8. package/lib/cjs/index.js +30 -0
  9. package/lib/cjs/injector/injector.js +141 -0
  10. package/{injector → lib/cjs/injector}/module.js +28 -26
  11. package/{metadata.js → lib/cjs/metadata.js} +31 -21
  12. package/lib/esm/exceptions/circularModuleImport.exception.js +19 -0
  13. package/lib/esm/exceptions/constant.message.js +8 -0
  14. package/lib/esm/exceptions/invalid.module.exception.js +18 -0
  15. package/lib/esm/exceptions/invalidProvider.module.exception.js +18 -0
  16. package/lib/esm/exceptions/missingInjectToken.exception.js +18 -0
  17. package/lib/esm/exceptions/resolution.exception.js +37 -0
  18. package/lib/esm/factory.js +210 -0
  19. package/lib/esm/index.js +9 -0
  20. package/{injector → lib/esm/injector}/injector.js +30 -17
  21. package/lib/esm/injector/module.js +213 -0
  22. package/lib/esm/metadata.js +164 -0
  23. package/lib/esm/package.json +1 -0
  24. package/lib/types/exceptions/circularModuleImport.exception.d.ts +13 -0
  25. package/{exceptions → lib/types/exceptions}/constant.message.d.ts +2 -0
  26. package/lib/types/exceptions/index.d.ts +6 -0
  27. package/lib/types/exceptions/missingInjectToken.exception.d.ts +12 -0
  28. package/lib/types/factory.d.ts +106 -0
  29. package/lib/types/index.d.ts +4 -0
  30. package/{injector → lib/types/injector}/injector.d.ts +2 -0
  31. package/{metadata.d.ts → lib/types/metadata.d.ts} +8 -1
  32. package/package.json +20 -4
  33. package/CHANGELOG.md +0 -336
  34. package/LICENSE +0 -33
  35. package/exceptions/index.d.ts +0 -2
  36. package/exceptions/index.js +0 -5
  37. package/exceptions/invalidProvider.module.exception.js +0 -19
  38. package/factory.d.ts +0 -55
  39. package/factory.js +0 -120
  40. package/index.d.ts +0 -3
  41. package/index.js +0 -8
  42. package/injector/index.js +0 -5
  43. package/interfaces/factory.interface.js +0 -2
  44. package/interfaces/globals.interface.js +0 -2
  45. package/interfaces/index.js +0 -5
  46. package/tsconfig.build.json +0 -17
  47. /package/{exceptions → lib/types/exceptions}/invalid.module.exception.d.ts +0 -0
  48. /package/{exceptions → lib/types/exceptions}/invalidProvider.module.exception.d.ts +0 -0
  49. /package/{exceptions → lib/types/exceptions}/resolution.exception.d.ts +0 -0
  50. /package/{injector → lib/types/injector}/index.d.ts +0 -0
  51. /package/{injector → lib/types/injector}/module.d.ts +0 -0
  52. /package/{interfaces → lib/types/interfaces}/factory.interface.d.ts +0 -0
  53. /package/{interfaces → lib/types/interfaces}/globals.interface.d.ts +0 -0
  54. /package/{interfaces → lib/types/interfaces}/index.d.ts +0 -0
@@ -1,7 +1,7 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Metadata = void 0;
4
- const constants_1 = require("@zanobijs/common/utils/constants");
1
+ 'use strict';
2
+
3
+ var constants = require('@zanobijs/common/utils/constants');
4
+
5
5
  /**
6
6
  * La clase `Metadata` proporciona métodos para acceder y manipular
7
7
  * metadatos relacionados con diversos componentes y módulos.
@@ -9,11 +9,11 @@ const constants_1 = require("@zanobijs/common/utils/constants");
9
9
  class Metadata {
10
10
  static instance;
11
11
  metadataMap = {
12
- [constants_1.IS_MODULE]: 'module',
13
- [constants_1.IS_IMPORTS]: 'import',
14
- [constants_1.IS_CONTROLLER]: 'controller',
15
- [constants_1.IS_SERVICE]: 'service',
16
- [constants_1.IS_EXPORT]: 'export',
12
+ [constants.IS_MODULE]: 'module',
13
+ [constants.IS_IMPORTS]: 'import',
14
+ [constants.IS_CONTROLLER]: 'controller',
15
+ [constants.IS_SERVICE]: 'service',
16
+ [constants.IS_EXPORT]: 'export',
17
17
  };
18
18
  constructor() { }
19
19
  /**
@@ -36,10 +36,10 @@ class Metadata {
36
36
  */
37
37
  getMetadataModule(module) {
38
38
  return {
39
- imports: Reflect.getMetadata(constants_1.MODULE_IMPORTS, module),
40
- controllers: Reflect.getMetadata(constants_1.MODULE_CONTROLLERS, module),
41
- services: Reflect.getMetadata(constants_1.MODULE_SERVICES, module),
42
- exports: Reflect.getMetadata(constants_1.MODULE_EXPORTS, module),
39
+ imports: Reflect.getMetadata(constants.MODULE_IMPORTS, module),
40
+ controllers: Reflect.getMetadata(constants.MODULE_CONTROLLERS, module),
41
+ services: Reflect.getMetadata(constants.MODULE_SERVICES, module),
42
+ exports: Reflect.getMetadata(constants.MODULE_EXPORTS, module),
43
43
  };
44
44
  }
45
45
  /**
@@ -62,7 +62,7 @@ class Metadata {
62
62
  * @returns Las dependencias de clase de la clase.
63
63
  */
64
64
  getClassDependencies(target) {
65
- return Reflect.getMetadata(constants_1.DEPENDENCIES_CLASS, target);
65
+ return Reflect.getMetadata(constants.DEPENDENCIES_CLASS, target);
66
66
  }
67
67
  /**
68
68
  * Obtiene las dependencias de parámetro asociadas con una clase.
@@ -71,7 +71,7 @@ class Metadata {
71
71
  * @returns Las dependencias de parámetro de la clase.
72
72
  */
73
73
  getParameterDependencies(target) {
74
- return Reflect.getMetadata(constants_1.DEPENDENCIES_PARAMETERS, target);
74
+ return Reflect.getMetadata(constants.DEPENDENCIES_PARAMETERS, target);
75
75
  }
76
76
  /**
77
77
  * Obtiene las dependencias a inyectar asociadas con una clase.
@@ -80,7 +80,16 @@ class Metadata {
80
80
  * @returns Un Map con las dependencias a inyectar de la clase.
81
81
  */
82
82
  getInjectionDependencies(target) {
83
- return Reflect.getMetadata(constants_1.DEPENDENCIES_INJECT, target) || new Map();
83
+ return Reflect.getMetadata(constants.DEPENDENCIES_INJECT, target) || new Map();
84
+ }
85
+ /**
86
+ * Obtiene el lifetime declarado en `@Injectable`/`@Controller` de una clase.
87
+ *
88
+ * @param { TClass } target - La función/clase objetivo.
89
+ * @returns El lifetime de la clase. `'singleton'` si no se declaró ninguno.
90
+ */
91
+ getLifetime(target) {
92
+ return Reflect.getMetadata(constants.LIFETIME_CLASS, target) ?? 'singleton';
84
93
  }
85
94
  /**
86
95
  * Determina el tipo de una clase basado en sus metadatos.
@@ -114,7 +123,7 @@ class Metadata {
114
123
  * @returns Verdadero si el target es de tipo "module", falso en caso contrario.
115
124
  */
116
125
  isTypeModule(target) {
117
- return this.hasMetadata(constants_1.IS_MODULE, target);
126
+ return this.hasMetadata(constants.IS_MODULE, target);
118
127
  }
119
128
  /**
120
129
  * Verifica si una clase es de tipo "import".
@@ -123,7 +132,7 @@ class Metadata {
123
132
  * @returns Verdadero si el target es de tipo "import", falso en caso contrario.
124
133
  */
125
134
  isTypeImport(target) {
126
- return this.hasMetadata(constants_1.IS_IMPORTS, target);
135
+ return this.hasMetadata(constants.IS_IMPORTS, target);
127
136
  }
128
137
  /**
129
138
  * Verifica si una clase es de tipo "controller".
@@ -132,7 +141,7 @@ class Metadata {
132
141
  * @returns Verdadero si el target es de tipo "controller", falso en caso contrario.
133
142
  */
134
143
  isTypeController(target) {
135
- return this.hasMetadata(constants_1.IS_CONTROLLER, target);
144
+ return this.hasMetadata(constants.IS_CONTROLLER, target);
136
145
  }
137
146
  /**
138
147
  * Verifica si una clase es de tipo "service".
@@ -141,7 +150,7 @@ class Metadata {
141
150
  * @returns Verdadero si el target es de tipo "service", falso en caso contrario.
142
151
  */
143
152
  isTypeService(target) {
144
- return this.hasMetadata(constants_1.IS_SERVICE, target);
153
+ return this.hasMetadata(constants.IS_SERVICE, target);
145
154
  }
146
155
  /**
147
156
  * Verifica si una clase es de tipo "export".
@@ -150,7 +159,8 @@ class Metadata {
150
159
  * @returns Verdadero si el target es de tipo "export", falso en caso contrario.
151
160
  */
152
161
  isTypeExports(target) {
153
- return this.hasMetadata(constants_1.IS_EXPORT, target);
162
+ return this.hasMetadata(constants.IS_EXPORT, target);
154
163
  }
155
164
  }
165
+
156
166
  exports.Metadata = Metadata;
@@ -0,0 +1,19 @@
1
+ import { RuntimeException } from '@zanobijs/common/exceptions/runtime.exception';
2
+ import { CIRCULAR_MODULE_IMPORT_ERROR } from './constant.message.js';
3
+
4
+ /**
5
+ * Excepción lanzada cuando el grafo de `imports` entre módulos contiene un
6
+ * ciclo: un módulo importa, directa o indirectamente, a otro módulo que ya
7
+ * lo está importando a él.
8
+ *
9
+ * @remarks
10
+ * Esta clase extiende la base `RuntimeException` de @zanobijs/common
11
+ * para proporcionar detalles adicionales del error.
12
+ */
13
+ class CircularModuleImportException extends RuntimeException {
14
+ constructor(chain) {
15
+ super(CIRCULAR_MODULE_IMPORT_ERROR(chain));
16
+ }
17
+ }
18
+
19
+ export { CircularModuleImportException };
@@ -0,0 +1,8 @@
1
+ const MODULE_INVALID_ANNOTATION_ERROR = () => 'The class must have an annotation @Module()';
2
+ const CONTAINER_RESOLUTION_ERROR = (entity, resolutionError) => `${resolutionError} please review '${entity}' and its dependencies.`;
3
+ const CONTAINER_RESOLUTION_ENTITY_ERROR = (entity) => `Please check that the entity '${entity}' exists and is registered in @modulo`;
4
+ const PROVIDER_INVALID_MODULE_ERROR = (entity, moduleName) => `Please check that ${entity} located in the @module ${moduleName} exists and is @Injectable().`;
5
+ const MISSING_INJECT_TOKEN_ERROR = (token, targetName, moduleName) => `Cannot inject @Inject('${token}') into '${targetName}': the provider '${token}' is not registered in '${moduleName}' or any other previously loaded module.`;
6
+ const CIRCULAR_MODULE_IMPORT_ERROR = (chain) => `Circular module import detected: ${chain}. A module cannot import, directly or indirectly, another module that already imports it.`;
7
+
8
+ export { CIRCULAR_MODULE_IMPORT_ERROR, CONTAINER_RESOLUTION_ENTITY_ERROR, CONTAINER_RESOLUTION_ERROR, MISSING_INJECT_TOKEN_ERROR, MODULE_INVALID_ANNOTATION_ERROR, PROVIDER_INVALID_MODULE_ERROR };
@@ -0,0 +1,18 @@
1
+ import { RuntimeException } from '@zanobijs/common/exceptions/runtime.exception';
2
+ import { MODULE_INVALID_ANNOTATION_ERROR } from './constant.message.js';
3
+
4
+ /**
5
+ * Excepción lanzada cuando una clase Modulo no tiene el decorador `@Module`
6
+ * de @zanobijs/common
7
+ *
8
+ * @remarks
9
+ * Esta clase extiende la base `RuntimeException`de @zanobijs/common
10
+ * para proporcionar detalles adicionales específicos a esquemas de módulos inválidos.
11
+ */
12
+ class InvalidModuleAnnotationException extends RuntimeException {
13
+ constructor(detail = '') {
14
+ super(MODULE_INVALID_ANNOTATION_ERROR(), detail);
15
+ }
16
+ }
17
+
18
+ export { InvalidModuleAnnotationException };
@@ -0,0 +1,18 @@
1
+ import { RuntimeException } from '@zanobijs/common/exceptions/runtime.exception';
2
+ import { PROVIDER_INVALID_MODULE_ERROR } from './constant.message.js';
3
+
4
+ /**
5
+ * Excepción lanzada cuando una clase Modulo no tiene un provedor definido correctamente
6
+ * de @zanobijs/common
7
+ *
8
+ * @remarks
9
+ * Esta clase extiende la base `RuntimeException`de @zanobijs/common
10
+ * para proporcionar detalles adicionales específicos a esquemas de módulos inválidos.
11
+ */
12
+ class InvalidProviderModuleException extends RuntimeException {
13
+ constructor(entity, moduleName, detail) {
14
+ super(PROVIDER_INVALID_MODULE_ERROR(entity, moduleName), detail);
15
+ }
16
+ }
17
+
18
+ export { InvalidProviderModuleException };
@@ -0,0 +1,18 @@
1
+ import { RuntimeException } from '@zanobijs/common/exceptions/runtime.exception';
2
+ import { MISSING_INJECT_TOKEN_ERROR } from './constant.message.js';
3
+
4
+ /**
5
+ * Excepción lanzada cuando un `@Inject(token)` no encuentra su provider
6
+ * registrado, ni en el módulo actual ni en ninguno de los módulos importados.
7
+ *
8
+ * @remarks
9
+ * Esta clase extiende la base `RuntimeException` de @zanobijs/common
10
+ * para proporcionar detalles adicionales del error.
11
+ */
12
+ class MissingInjectTokenException extends RuntimeException {
13
+ constructor(token, targetName, moduleName) {
14
+ super(MISSING_INJECT_TOKEN_ERROR(token, targetName, moduleName));
15
+ }
16
+ }
17
+
18
+ export { MissingInjectTokenException };
@@ -0,0 +1,37 @@
1
+ import { RuntimeException } from '@zanobijs/common/exceptions/runtime.exception';
2
+ import { CONTAINER_RESOLUTION_ENTITY_ERROR, CONTAINER_RESOLUTION_ERROR } from './constant.message.js';
3
+
4
+ /**
5
+ * Excepción lanzada cuando se intenta obtener una dependencia
6
+ * de un controlador o servicio y esta no fue registrada
7
+ * en un modulo
8
+ *
9
+ * @remarks
10
+ * Esta clase extiende la base `RuntimeException`de @zanobijs/core
11
+ * para proporcionar detalles adicionales del error.
12
+ *
13
+ * @example
14
+ * private service1: Service1
15
+ * @Module{... services:["otherService"]}
16
+ */
17
+ class ContainerResolutionException extends RuntimeException {
18
+ constructor(entity, resolutionError, detail) {
19
+ super(CONTAINER_RESOLUTION_ERROR(entity, resolutionError), detail);
20
+ }
21
+ }
22
+ /**
23
+ * Excepción lanzada cuando se intenta obtener una entidad
24
+ * (importar, controlador, servicio o exportar) que no fue
25
+ * declarada en `@Module` de @zanobijs/common
26
+ *
27
+ * @remarks
28
+ * Esta clase extiende la base `RuntimeException`de @zanobijs/core
29
+ * para proporcionar detalles adicionales del error.
30
+ */
31
+ class ContainerResolutionEntityException extends RuntimeException {
32
+ constructor(entity, detail) {
33
+ super(CONTAINER_RESOLUTION_ENTITY_ERROR(entity), detail);
34
+ }
35
+ }
36
+
37
+ export { ContainerResolutionEntityException, ContainerResolutionException };
@@ -0,0 +1,210 @@
1
+ import 'reflect-metadata';
2
+ import { createContainer, InjectionMode, AwilixResolutionError } from 'awilix';
3
+ import { Module } from './injector/module.js';
4
+ import { ContainerResolutionEntityException, ContainerResolutionException } from './exceptions/resolution.exception.js';
5
+ import { CircularModuleImportException } from './exceptions/circularModuleImport.exception.js';
6
+ import { Logger } from '@zanobijs/common/utils';
7
+
8
+ /**
9
+ * Resuelve `className` desde `container` traduciendo los errores de `awilix`
10
+ * al vocabulario de excepciones de `ZanobiJS`. Compartido entre `Factory.get()`
11
+ * y `RequestScope.get()` para no duplicar el manejo de `AwilixResolutionError`.
12
+ * @throws {ContainerResolutionEntityException | ContainerResolutionException}
13
+ * Si `awilix` no logra resolver la entidad o alguna de sus dependencias.
14
+ * @throws Propaga sin modificar cualquier otro error (p. ej. uno lanzado por
15
+ * el propio constructor de la clase que se está resolviendo).
16
+ */
17
+ function resolveEntity(container, className, logger) {
18
+ try {
19
+ return container.resolve(className);
20
+ }
21
+ catch (error) {
22
+ if (!(error instanceof AwilixResolutionError)) {
23
+ throw error;
24
+ }
25
+ logger.info('Error resolving entity: ', error.message + '\n');
26
+ const resolutionError = error.message.split('\n');
27
+ const classNameFound = resolutionError[0].match(/'([^']+)'/);
28
+ if (classNameFound?.[1] === className) {
29
+ throw new ContainerResolutionEntityException(className, error.message);
30
+ }
31
+ throw new ContainerResolutionException(className, resolutionError[0], error.message);
32
+ }
33
+ }
34
+ /**
35
+ * Handle atado a un scope de `awilix` puntual (una copia liviana del
36
+ * contenedor raíz, ver `Factory.createRequestScope`). Resuelve entidades
37
+ * `singleton` desde el contenedor raíz (reusadas, gratis) y entidades
38
+ * `request` desde este scope (instancia nueva, se descarta con él).
39
+ */
40
+ class RequestScope {
41
+ container;
42
+ logger;
43
+ constructor(container, logger) {
44
+ this.container = container;
45
+ this.logger = logger;
46
+ }
47
+ /**
48
+ * Resuelve y devuelve una instancia del scope teniendo en cuenta el
49
+ * nombre de la entidad proporcionada.
50
+ * @param {string} className - Nombre de la entidad a resolver.
51
+ * @returns {T} - Instancia resuelta.
52
+ */
53
+ get(className) {
54
+ return resolveEntity(this.container, className, this.logger);
55
+ }
56
+ }
57
+ /**
58
+ * Factory es una clase que facilita la creación y configuración de
59
+ * contenedores de inyección de dependencias utilizando metadatos y
60
+ * la librería `awilix` para registrar y resolver entidades como:
61
+ * controladores y servicios.
62
+ */
63
+ class Factory {
64
+ moduleHandler;
65
+ registeredClasses = {};
66
+ container;
67
+ logger;
68
+ options;
69
+ scannedModules = new Set();
70
+ processedModules = new Set();
71
+ constructor(appModule, options = {}) {
72
+ this.options = options;
73
+ this.evaluateOptions();
74
+ this.logger = Logger();
75
+ this.moduleHandler = new Module();
76
+ this.scanProviderModule(appModule);
77
+ this.registerProviderScanedModules();
78
+ this.processClassModule(appModule);
79
+ }
80
+ /**
81
+ * Se encarga de escaenear modulo por modulo los proveedores con el fin de luego
82
+ * poder ser registrados e inyectados en quien depende de ese proveedor
83
+ * @param {TClass} module - Módulo desde el que se escanearan los proveedores.
84
+ * @param {TClass[]} path - Cadena de módulos ancestros en la recursión actual,
85
+ * usada para detectar ciclos de imports.
86
+ * @private
87
+ * @throws {CircularModuleImportException} Si `module` ya está en `path`.
88
+ */
89
+ scanProviderModule(module, path = []) {
90
+ if (path.includes(module)) {
91
+ throw new CircularModuleImportException([...path, module].map((m) => m.name).join(' -> '));
92
+ }
93
+ /** Un mismo módulo puede llegar por varias ramas del grafo de imports
94
+ * (ej. un CommonModule importado por varios módulos de feature). No es
95
+ * un error: ya fue escaneado, no hay nada más que hacer aquí. */
96
+ if (this.scannedModules.has(module)) {
97
+ return;
98
+ }
99
+ this.scannedModules.add(module);
100
+ this.logger.debug('Factory - Scan Module:', module.name);
101
+ this.moduleHandler.setup(module);
102
+ this.moduleHandler.scan();
103
+ this.logger.debug('===================================================');
104
+ const importedModules = this.moduleHandler.getImports();
105
+ if (importedModules && importedModules.length) {
106
+ const nextPath = [...path, module];
107
+ importedModules.forEach((moduleImport) => {
108
+ this.scanProviderModule(moduleImport, nextPath);
109
+ });
110
+ }
111
+ }
112
+ /**
113
+ * Se encarga tomar la lista de proveedores y registralos para luego se resueltos
114
+ * cuando el usuario lo solicite
115
+ * @private
116
+ */
117
+ registerProviderScanedModules() {
118
+ this.moduleHandler.registerAllProviders();
119
+ }
120
+ /**
121
+ * Procesa modulo por modulos registrando los controladores, servicios y proveedores,
122
+ * estos se le irá inyectando sus dependecias resueltas para ser usados por el usuario
123
+ * @param {TClass} module - Módulo desde el que se registrarán las clases.
124
+ * @private
125
+ *
126
+ * @remarks
127
+ * No repite la detección de ciclos: `scanProviderModule` ya recorrió este
128
+ * mismo grafo de imports antes (misma metadata, mismas aristas) y habría
129
+ * lanzado `CircularModuleImportException` si existiera uno. Solo se
130
+ * deduplica por módulo (`processedModules`) para el caso de diamante.
131
+ */
132
+ processClassModule(module) {
133
+ if (this.processedModules.has(module)) {
134
+ return;
135
+ }
136
+ this.processedModules.add(module);
137
+ this.logger.debug('Factory - Process Class Module:', module.name);
138
+ this.moduleHandler.setup(module);
139
+ this.moduleHandler.initialize();
140
+ Object.assign(this.registeredClasses, this.moduleHandler.getRegisterClass());
141
+ this.logger.success('Factory - Process Class Module - Completion!!!', module.name);
142
+ const importedModules = this.moduleHandler.getImports();
143
+ if (importedModules && importedModules.length) {
144
+ importedModules.forEach((moduleImport) => {
145
+ this.processClassModule(moduleImport);
146
+ });
147
+ }
148
+ this.logger.debug('===================================================');
149
+ }
150
+ /**
151
+ * Crea el contenedor de inyección de dependencias y registra el listado de
152
+ * controladores, servicio y proveedores que se ha venido creando a parti de escaneos
153
+ * y registros de clases.
154
+ * @returns {Factory} - Instancia actual de la fábrica.
155
+ */
156
+ create() {
157
+ this.container = createContainer({
158
+ injectionMode: InjectionMode.CLASSIC,
159
+ strict: true,
160
+ });
161
+ this.container.register(this.registeredClasses);
162
+ this.logger.info('Factory - classes and providers registered in the container', Object.keys(this.registeredClasses));
163
+ return this;
164
+ }
165
+ /**
166
+ * Resuelve y devuelve una instancia del contenedor
167
+ * teniendo en cuenta el nombre de la entidad proporcionada.
168
+ * @param {string} className - Nombre de la entidad a resolver.
169
+ * @returns {T} - Instancia resuelta.
170
+ * @throws {ContainerResolutionEntityException | ContainerResolutionException}
171
+ * Si `awilix` no logra resolver la entidad o alguna de sus dependencias.
172
+ * @throws Propaga sin modificar cualquier otro error (p. ej. uno lanzado por
173
+ * el propio constructor de la clase que se está resolviendo).
174
+ */
175
+ get(className) {
176
+ return resolveEntity(this.container, className, this.logger);
177
+ }
178
+ /**
179
+ * Crea una copia liviana del contenedor raíz para usar durante una
180
+ * única invocación/petición (Lambda, Azure Function, request HTTP...).
181
+ *
182
+ * Las entidades `singleton` se reusan tal cual desde el contenedor raíz
183
+ * (cero costo). Las entidades con `lifetime: 'request'` (ver `@Injectable`)
184
+ * se resuelven de cero dentro de este scope y se descartan junto con él.
185
+ *
186
+ * @returns {RequestScope} - Handle atado a este scope puntual.
187
+ */
188
+ createRequestScope() {
189
+ const scope = this.container.createScope();
190
+ return new RequestScope(scope, this.logger);
191
+ }
192
+ /**
193
+ * Se encarga de evaluar las opciones para ver si o no aplica y realizar lo correspondiente
194
+ *
195
+ * `ZANOBIJS_LOGGER`/`ZANOBIJS_LOGGER_USER` son pensadas para poder prenderse/apagarse
196
+ * desde la configuración de despliegue (variables de entorno de Lambda/contenedor) sin
197
+ * tocar código ni redeployar. Por eso, si el operador ya las configuró externamente,
198
+ * NO se pisan — `options` solo aplica como default cuando la variable no existe.
199
+ */
200
+ evaluateOptions() {
201
+ if (process.env.ZANOBIJS_LOGGER === undefined) {
202
+ process.env.ZANOBIJS_LOGGER = String(this.options.activeLoggerSystem ?? false);
203
+ }
204
+ if (process.env.ZANOBIJS_LOGGER_USER === undefined) {
205
+ process.env.ZANOBIJS_LOGGER_USER = String(this.options.activeLoggerUser ?? false);
206
+ }
207
+ }
208
+ }
209
+
210
+ export { Factory, RequestScope };
@@ -0,0 +1,9 @@
1
+ export { Factory, RequestScope } from './factory.js';
2
+ export { Module } from './injector/module.js';
3
+ export { Injector } from './injector/injector.js';
4
+ export { CIRCULAR_MODULE_IMPORT_ERROR, CONTAINER_RESOLUTION_ENTITY_ERROR, CONTAINER_RESOLUTION_ERROR, MISSING_INJECT_TOKEN_ERROR, MODULE_INVALID_ANNOTATION_ERROR, PROVIDER_INVALID_MODULE_ERROR } from './exceptions/constant.message.js';
5
+ export { InvalidModuleAnnotationException } from './exceptions/invalid.module.exception.js';
6
+ export { InvalidProviderModuleException } from './exceptions/invalidProvider.module.exception.js';
7
+ export { MissingInjectTokenException } from './exceptions/missingInjectToken.exception.js';
8
+ export { CircularModuleImportException } from './exceptions/circularModuleImport.exception.js';
9
+ export { ContainerResolutionEntityException, ContainerResolutionException } from './exceptions/resolution.exception.js';
@@ -1,10 +1,19 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Injector = void 0;
4
- const metadata_1 = require("../metadata");
5
- const utils_1 = require("@zanobijs/common/utils");
6
- const shared_utils_1 = require("@zanobijs/common/utils/shared.utils");
7
- const awilix_1 = require("awilix");
1
+ import { Metadata } from '../metadata.js';
2
+ import { Logger } from '@zanobijs/common/utils';
3
+ import { isClass, isEmpty } from '@zanobijs/common/utils/shared.utils';
4
+ import { asFunction, asValue, asClass } from 'awilix';
5
+ import { MissingInjectTokenException } from '../exceptions/missingInjectToken.exception.js';
6
+
7
+ /**
8
+ * Mapea el `lifetime` público de `ZanobiJS` al método fluido de `awilix`.
9
+ * `request` usa `Lifetime.SCOPED` de `awilix` internamente: sin un scope real
10
+ * creado (ver `Factory.createRequestScope`), se resuelve igual que `singleton`.
11
+ */
12
+ const LIFETIME_METHOD = {
13
+ singleton: 'singleton',
14
+ request: 'scoped',
15
+ transient: 'transient',
16
+ };
8
17
  /**
9
18
  * La clase `Injector` es la encargada de manejar la inyección de dependencias
10
19
  * solo para parametros tipo objecto { provider, useValue }
@@ -23,8 +32,8 @@ class Injector {
23
32
  * para poderlo procesar.
24
33
  */
25
34
  constructor(module, listProviders, listProvidersClass) {
26
- this.metadata = metadata_1.Metadata.getInstance();
27
- this.logger = (0, utils_1.Logger)();
35
+ this.metadata = Metadata.getInstance();
36
+ this.logger = Logger();
28
37
  this.moduleName = module.name;
29
38
  this.module = module;
30
39
  this.listProviders = listProviders;
@@ -46,16 +55,16 @@ class Injector {
46
55
  this.listProvidersClass.set(key, service.useClass);
47
56
  }
48
57
  else if (service.useFactory) {
49
- this.listProviders.set(key, (0, awilix_1.asFunction)(service.useFactory).scoped());
58
+ this.listProviders.set(key, asFunction(service.useFactory).scoped());
50
59
  }
51
60
  else {
52
- this.listProviders.set(key, (0, awilix_1.asValue)(service.useValue));
61
+ this.listProviders.set(key, asValue(service.useValue));
53
62
  }
54
63
  }
55
- if (typeof service === 'object' && (0, shared_utils_1.isClass)(service.provider)) {
64
+ if (typeof service === 'object' && isClass(service.provider)) {
56
65
  let useExample = false;
57
66
  const key = service.provider.name;
58
- if (service.useClass && (0, shared_utils_1.isClass)(service.useClass)) {
67
+ if (service.useClass && isClass(service.useClass)) {
59
68
  this.listProvidersClass.set(key, service.useClass);
60
69
  }
61
70
  else {
@@ -79,6 +88,8 @@ class Injector {
79
88
  *
80
89
  * @param { TClass} target - La clase objetivo.
81
90
  * @returns {object} - Objeto con datos a inyectar.
91
+ * @throws {MissingInjectTokenException} Si un `@Inject(token)` de `target` no tiene
92
+ * su provider registrado en este módulo ni en ninguno de los módulos importados.
82
93
  */
83
94
  getInjectData(target) {
84
95
  const injectData = {};
@@ -91,7 +102,7 @@ class Injector {
91
102
  injectData[paramName] = providerValue.resolve();
92
103
  }
93
104
  else {
94
- this.logger.important(`You are trying to inject @INJECT('${key}') into '${target.name}'`, `but the provider '${key}' and its value are not registered in '${this.moduleName}' or any other previously loaded modules`);
105
+ throw new MissingInjectTokenException(key, target.name, this.moduleName);
95
106
  }
96
107
  }
97
108
  }
@@ -109,8 +120,9 @@ class Injector {
109
120
  */
110
121
  getInjectorClass(target) {
111
122
  const injectData = this.getInjectData(target);
112
- let injector = (0, awilix_1.asClass)(target).scoped();
113
- if (!(0, shared_utils_1.isEmpty)(injectData)) {
123
+ const lifetime = this.metadata.getLifetime(target);
124
+ let injector = asClass(target)[LIFETIME_METHOD[lifetime]]();
125
+ if (!isEmpty(injectData)) {
114
126
  this.logger.debug(`Inject - list dependencies to inject of ${target.name}:`, injectData);
115
127
  injector = injector.inject(() => injectData);
116
128
  }
@@ -123,4 +135,5 @@ class Injector {
123
135
  return this.listProviders;
124
136
  }
125
137
  }
126
- exports.Injector = Injector;
138
+
139
+ export { Injector };