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