@zanobijs/core 1.0.0-beta.1

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 (61) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +33 -0
  3. package/README.md +11 -0
  4. package/__test__/factory.spec.d.ts +1 -0
  5. package/__test__/factory.spec.js +33 -0
  6. package/__test__/factory.spec.ts +37 -0
  7. package/__test__/injector/injector.spec.d.ts +1 -0
  8. package/__test__/injector/injector.spec.js +32 -0
  9. package/__test__/injector/injector.spec.ts +32 -0
  10. package/__test__/injector/module.spec.d.ts +1 -0
  11. package/__test__/injector/module.spec.js +60 -0
  12. package/__test__/injector/module.spec.ts +66 -0
  13. package/__test__/metadata.spec.d.ts +1 -0
  14. package/__test__/metadata.spec.js +70 -0
  15. package/__test__/metadata.spec.ts +71 -0
  16. package/__test__/mocks/classModule.mock.d.ts +10 -0
  17. package/__test__/mocks/classModule.mock.js +74 -0
  18. package/__test__/mocks/classModule.mock.ts +55 -0
  19. package/__test__/mocks/classWithDependeciesClass.mock.d.ts +13 -0
  20. package/__test__/mocks/classWithDependeciesClass.mock.js +40 -0
  21. package/__test__/mocks/classWithDependeciesClass.mock.ts +21 -0
  22. package/__test__/mocks/classWithDependeciesInject.mock.d.ts +24 -0
  23. package/__test__/mocks/classWithDependeciesInject.mock.js +74 -0
  24. package/__test__/mocks/classWithDependeciesInject.mock.ts +47 -0
  25. package/__test__/mocks/index.d.ts +1 -0
  26. package/__test__/mocks/index.js +4 -0
  27. package/__test__/mocks/index.ts +1 -0
  28. package/exceptions/constant.message.d.ts +1 -0
  29. package/exceptions/constant.message.js +5 -0
  30. package/exceptions/constant.message.ts +1 -0
  31. package/exceptions/index.d.ts +2 -0
  32. package/exceptions/index.js +5 -0
  33. package/exceptions/index.ts +2 -0
  34. package/exceptions/invalid.module.exception.d.ts +12 -0
  35. package/exceptions/invalid.module.exception.js +19 -0
  36. package/exceptions/invalid.module.exception.ts +16 -0
  37. package/factory.d.ts +37 -0
  38. package/factory.js +64 -0
  39. package/factory.ts +69 -0
  40. package/index.d.ts +2 -0
  41. package/index.js +7 -0
  42. package/index.ts +2 -0
  43. package/injector/index.d.ts +2 -0
  44. package/injector/index.js +5 -0
  45. package/injector/index.ts +2 -0
  46. package/injector/injector.d.ts +60 -0
  47. package/injector/injector.js +83 -0
  48. package/injector/injector.ts +89 -0
  49. package/injector/module.d.ts +76 -0
  50. package/injector/module.js +135 -0
  51. package/injector/module.ts +149 -0
  52. package/interface/index.d.ts +0 -0
  53. package/interface/index.js +1 -0
  54. package/interface/index.ts +1 -0
  55. package/metadata.d.ts +106 -0
  56. package/metadata.js +155 -0
  57. package/metadata.ts +178 -0
  58. package/package.json +34 -0
  59. package/tsconfig.build.json +17 -0
  60. package/tsconfig.build.tsbuildinfo +1 -0
  61. package/tsconfig.json +11 -0
@@ -0,0 +1,89 @@
1
+ import { ILoggerService, IModuleConfig } from "zanobijs-common";
2
+ import { Metadata } from "../metadata";
3
+ import { Logger } from "zanobijs-common/utils";
4
+ import { isEmpty } from "zanobijs-common/utils/shared.utils";
5
+ import { asClass } from "awilix";
6
+
7
+ export type Constructor<T> = { new (...args: any[]): T }
8
+
9
+ /**
10
+ * La clase `Injector` es la encargada de manejar la inyección de dependencias
11
+ * solo para parametros tipo objecto { provider, useValue }
12
+ */
13
+ export class Injector {
14
+ private module: IModuleConfig;
15
+ private listProviders = new Map();
16
+ private metadata: Metadata;
17
+ private logger: ILoggerService;
18
+
19
+ /**
20
+ * En Constructor de la clase Injector obtenermos las instancias
21
+ * de Metadata y Logger e inciamos el escaneo de proveedores.
22
+ * @param {Module} module - El módulo debe tener el decorador `@Module`
23
+ * para poderlo procesar.
24
+ */
25
+ constructor(module: any) {
26
+ this.metadata = Metadata.getInstance();
27
+ this.logger = Logger();
28
+ this.module = module;
29
+ this.scanProviders();
30
+ }
31
+
32
+ /**
33
+ * Este método privado recorre el array de los servicios del modulo para
34
+ * buscar los proveedores tipo objeto a injectar y los almacena en una
35
+ * lista de proveedores.
36
+ * @private
37
+ */
38
+ private scanProviders() {
39
+ const { services } = this.metadata.getMetadataModule(this.module);
40
+ services.forEach((service) => {
41
+ if (typeof service === "object")
42
+ this.listProviders.set(service.provider, service.useValue);
43
+ });
44
+ this.logger.debug("Injector - list provider", this.listProviders);
45
+ }
46
+
47
+ /**
48
+ * Método para obtener un objeto con los parámetros y valores
49
+ * que se inyectarán en la clase (target).
50
+ *
51
+ * @param {Class} target - La clase objetivo.
52
+ * @returns {object} - Objeto con datos a inyectar.
53
+ */
54
+ getInjectData(target: Function): object {
55
+ const injectData = {};
56
+ const dInject = this.metadata.getInjectionDependencies(target);
57
+ if (dInject.size > 0) {
58
+ for (const key of dInject.keys()) {
59
+ if (this.listProviders.has(key)) {
60
+ this.logger.info(`"${key}" is on providers list.`);
61
+ const paramName = dInject.get(key);
62
+ const useValue = this.listProviders.get(key);
63
+ injectData[paramName] = useValue;
64
+ }
65
+ }
66
+ }
67
+ return injectData;
68
+ }
69
+
70
+ /**
71
+ * Método para obtener el injector apropiado para la clase objetivo.
72
+ *
73
+ * @param {any} target - La clase objetivo.
74
+ * @returns - El injector configurado.
75
+ */
76
+ getInjector(target) {
77
+ const injectData = this.getInjectData(target);
78
+ let injector = asClass(target).scoped();
79
+
80
+ if (!isEmpty(injectData)) {
81
+ injector = injector.inject(() => injectData);
82
+ }
83
+
84
+ return {
85
+ ...injector,
86
+ interface: target,
87
+ };
88
+ }
89
+ }
@@ -0,0 +1,76 @@
1
+ import "reflect-metadata";
2
+ /**
3
+ * Módulo para gestionar la configuración y el registro de controladores, servicios y dependencias.
4
+ */
5
+ export declare class Module {
6
+ private config;
7
+ private module;
8
+ private logger;
9
+ private injector;
10
+ private registerClass;
11
+ private dependenciesClass;
12
+ private metadata;
13
+ private types;
14
+ /**
15
+ * Constructor del módulo.
16
+ */
17
+ constructor();
18
+ /**
19
+ * Configura el módulo con la información proporcionada.
20
+ * @param {any} module - Módulo a configurar.
21
+ */
22
+ setup(module: any): void;
23
+ /**
24
+ * Inicializa el módulo extrayendo metadatos y registrando las entidades.
25
+ */
26
+ initialize(): void;
27
+ /**
28
+ * Extrae los metadatos del módulo usando reflect-metadata.
29
+ * @private
30
+ */
31
+ private getMetadataModule;
32
+ /**
33
+ * Registra las entidades de configuración en el módulo.
34
+ * @private
35
+ */
36
+ private registerDependencies;
37
+ /**
38
+ * Registra entidades de configuración (controladores o servicios) del módulo.
39
+ * @param {('controllers' | 'services')} entityType - Tipo de entidad a registrar.
40
+ * @private
41
+ */
42
+ private registerEntities;
43
+ /**
44
+ * Agrupación de dependencias para alias
45
+ *
46
+ * Este método agrupa las dependencias de la clase utilizando el método
47
+ * `getClassDependencies` de la instancia `metadata`. Si la clase
48
+ * tiene dependencias y estas no están vacías, las añade a la propiedad
49
+ * `dependenciesClass` de la instancia actual para luego validar si existe
50
+ * alguna dependencia con un nombre diferente y asiganar un alias.
51
+ *
52
+ * @private
53
+ * @param {Function} target - La clase objetivo de la cual se quieren obtener las dependencias.
54
+ */
55
+ private groupDependenciesForAlias;
56
+ /**
57
+ * recorre las dependencias agrupadas y registra con un alias
58
+ * aquellas que tienen nombres diferente a la que esta registrada.
59
+ *
60
+ * @private
61
+ * @example
62
+ * contructor(private serviceA: ServiceA) // parametro con nombre igual
63
+ * contructor(private sA: ServiceA) // parametro con nombre diferente
64
+ */
65
+ private registerDependenciesToAlias;
66
+ /**
67
+ * Devuelve las importaciones del módulo.
68
+ * @returns {any[] | undefined} - Importaciones del módulo.
69
+ */
70
+ getImports(): any[] | undefined;
71
+ /**
72
+ * Devuelve las clases registradas en el módulo.
73
+ * @returns {any} - Clases registradas.
74
+ */
75
+ getRegisterClass(): any;
76
+ }
@@ -0,0 +1,135 @@
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
+ /**
12
+ * Módulo para gestionar la configuración y el registro de controladores, servicios y dependencias.
13
+ */
14
+ class Module {
15
+ config;
16
+ module;
17
+ logger;
18
+ injector;
19
+ registerClass = {};
20
+ dependenciesClass = [];
21
+ metadata;
22
+ types = ["controller", "service"];
23
+ /**
24
+ * Constructor del módulo.
25
+ */
26
+ constructor() {
27
+ this.logger = (0, utils_1.Logger)();
28
+ this.metadata = metadata_1.Metadata.getInstance();
29
+ }
30
+ /**
31
+ * Configura el módulo con la información proporcionada.
32
+ * @param {any} module - Módulo a configurar.
33
+ */
34
+ setup(module) {
35
+ if (this.metadata.isTypeModule(module)) {
36
+ this.module = module;
37
+ this.injector = new injector_1.Injector(module);
38
+ }
39
+ else {
40
+ throw new exceptions_1.InvalidModuleAnnotationException();
41
+ }
42
+ }
43
+ /**
44
+ * Inicializa el módulo extrayendo metadatos y registrando las entidades.
45
+ */
46
+ initialize() {
47
+ this.getMetadataModule();
48
+ this.registerDependencies();
49
+ this.registerDependenciesToAlias();
50
+ }
51
+ /**
52
+ * Extrae los metadatos del módulo usando reflect-metadata.
53
+ * @private
54
+ */
55
+ getMetadataModule() {
56
+ this.config = this.metadata.getMetadataModule(this.module);
57
+ }
58
+ /**
59
+ * Registra las entidades de configuración en el módulo.
60
+ * @private
61
+ */
62
+ registerDependencies() {
63
+ this.registerEntities("controllers");
64
+ this.registerEntities("services");
65
+ }
66
+ /**
67
+ * Registra entidades de configuración (controladores o servicios) del módulo.
68
+ * @param {('controllers' | 'services')} entityType - Tipo de entidad a registrar.
69
+ * @private
70
+ */
71
+ registerEntities(entityType) {
72
+ const entities = this.config[entityType];
73
+ if (entities && entities.length > 0) {
74
+ const registeredEntities = entities
75
+ .filter((target) => (0, shared_utils_1.isClass)(target) &&
76
+ this.types.includes(this.metadata.determineType(target)))
77
+ .map((target) => {
78
+ this.groupDependenciesForAlias(target);
79
+ const targetName = (0, shared_utils_1.unCapitalize)(target.name);
80
+ return { [targetName]: this.injector.getInjector(target) };
81
+ });
82
+ Object.assign(this.registerClass, ...registeredEntities);
83
+ }
84
+ }
85
+ /**
86
+ * Agrupación de dependencias para alias
87
+ *
88
+ * Este método agrupa las dependencias de la clase utilizando el método
89
+ * `getClassDependencies` de la instancia `metadata`. Si la clase
90
+ * tiene dependencias y estas no están vacías, las añade a la propiedad
91
+ * `dependenciesClass` de la instancia actual para luego validar si existe
92
+ * alguna dependencia con un nombre diferente y asiganar un alias.
93
+ *
94
+ * @private
95
+ * @param {Function} target - La clase objetivo de la cual se quieren obtener las dependencias.
96
+ */
97
+ groupDependenciesForAlias(target) {
98
+ const dependencies = this.metadata.getClassDependencies(target);
99
+ if (dependencies && !(0, shared_utils_1.isEmpty)(dependencies)) {
100
+ this.dependenciesClass = [...this.dependenciesClass, ...dependencies];
101
+ }
102
+ }
103
+ /**
104
+ * recorre las dependencias agrupadas y registra con un alias
105
+ * aquellas que tienen nombres diferente a la que esta registrada.
106
+ *
107
+ * @private
108
+ * @example
109
+ * contructor(private serviceA: ServiceA) // parametro con nombre igual
110
+ * contructor(private sA: ServiceA) // parametro con nombre diferente
111
+ */
112
+ registerDependenciesToAlias() {
113
+ this.dependenciesClass.forEach((dependency) => {
114
+ if (!this.registerClass[dependency.nameParameter]) {
115
+ this.registerClass[dependency.nameParameter] = (0, awilix_1.aliasTo)(dependency.nameClassContainer);
116
+ }
117
+ });
118
+ }
119
+ /**
120
+ * Devuelve las importaciones del módulo.
121
+ * @returns {any[] | undefined} - Importaciones del módulo.
122
+ */
123
+ getImports() {
124
+ return this.config.imports;
125
+ }
126
+ /**
127
+ * Devuelve las clases registradas en el módulo.
128
+ * @returns {any} - Clases registradas.
129
+ */
130
+ getRegisterClass() {
131
+ this.logger.debug("Module - register class", this.registerClass);
132
+ return this.registerClass;
133
+ }
134
+ }
135
+ exports.Module = Module;
@@ -0,0 +1,149 @@
1
+ import "reflect-metadata";
2
+ import { aliasTo, asClass } from "awilix";
3
+ import { IModuleConfig, ILoggerService } from "zanobijs-common";
4
+ import { unCapitalize, isEmpty, isClass } from "zanobijs-common/utils/shared.utils";
5
+ import { Logger } from "zanobijs-common/utils";
6
+ import { Injector } from "./injector";
7
+ import { Metadata } from "../metadata";
8
+ import { InvalidModuleAnnotationException } from "../exceptions";
9
+
10
+ /**
11
+ * Módulo para gestionar la configuración y el registro de controladores, servicios y dependencias.
12
+ */
13
+ export class Module {
14
+ private config: IModuleConfig;
15
+ private module: any;
16
+ private logger: ILoggerService;
17
+ private injector: Injector;
18
+ private registerClass = {};
19
+ private dependenciesClass: any[] = [];
20
+ private metadata: Metadata;
21
+ private types: string[] = ["controller", "service"];
22
+
23
+ /**
24
+ * Constructor del módulo.
25
+ */
26
+ constructor() {
27
+ this.logger = Logger();
28
+ this.metadata = Metadata.getInstance();
29
+ }
30
+
31
+ /**
32
+ * Configura el módulo con la información proporcionada.
33
+ * @param {any} module - Módulo a configurar.
34
+ */
35
+ setup(module: any): void {
36
+ if (this.metadata.isTypeModule(module)) {
37
+ this.module = module;
38
+ this.injector = new Injector(module);
39
+ } else {
40
+ throw new InvalidModuleAnnotationException();
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Inicializa el módulo extrayendo metadatos y registrando las entidades.
46
+ */
47
+ initialize(): void {
48
+ this.getMetadataModule();
49
+ this.registerDependencies();
50
+ this.registerDependenciesToAlias();
51
+ }
52
+
53
+ /**
54
+ * Extrae los metadatos del módulo usando reflect-metadata.
55
+ * @private
56
+ */
57
+ private getMetadataModule(): void {
58
+ this.config = this.metadata.getMetadataModule(this.module);
59
+ }
60
+
61
+ /**
62
+ * Registra las entidades de configuración en el módulo.
63
+ * @private
64
+ */
65
+ private registerDependencies(): void {
66
+ this.registerEntities("controllers");
67
+ this.registerEntities("services");
68
+ }
69
+
70
+ /**
71
+ * Registra entidades de configuración (controladores o servicios) del módulo.
72
+ * @param {('controllers' | 'services')} entityType - Tipo de entidad a registrar.
73
+ * @private
74
+ */
75
+ private registerEntities(entityType: "controllers" | "services"): void {
76
+ const entities = this.config[entityType];
77
+
78
+ if (entities && entities.length > 0) {
79
+ const registeredEntities = entities
80
+ .filter(
81
+ (target) =>
82
+ isClass(target) &&
83
+ this.types.includes(this.metadata.determineType(target)),
84
+ )
85
+ .map((target) => {
86
+ this.groupDependenciesForAlias(target);
87
+ const targetName = unCapitalize(target.name);
88
+ return { [targetName]: this.injector.getInjector(target) };
89
+ });
90
+
91
+ Object.assign(this.registerClass, ...registeredEntities);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Agrupación de dependencias para alias
97
+ *
98
+ * Este método agrupa las dependencias de la clase utilizando el método
99
+ * `getClassDependencies` de la instancia `metadata`. Si la clase
100
+ * tiene dependencias y estas no están vacías, las añade a la propiedad
101
+ * `dependenciesClass` de la instancia actual para luego validar si existe
102
+ * alguna dependencia con un nombre diferente y asiganar un alias.
103
+ *
104
+ * @private
105
+ * @param {Function} target - La clase objetivo de la cual se quieren obtener las dependencias.
106
+ */
107
+ private groupDependenciesForAlias(target: Function): void {
108
+ const dependencies: any[] = this.metadata.getClassDependencies(target);
109
+ if (dependencies && !isEmpty(dependencies)) {
110
+ this.dependenciesClass = [...this.dependenciesClass, ...dependencies];
111
+ }
112
+ }
113
+
114
+ /**
115
+ * recorre las dependencias agrupadas y registra con un alias
116
+ * aquellas que tienen nombres diferente a la que esta registrada.
117
+ *
118
+ * @private
119
+ * @example
120
+ * contructor(private serviceA: ServiceA) // parametro con nombre igual
121
+ * contructor(private sA: ServiceA) // parametro con nombre diferente
122
+ */
123
+ private registerDependenciesToAlias(): void {
124
+ this.dependenciesClass.forEach((dependency) => {
125
+ if (!this.registerClass[dependency.nameParameter]) {
126
+ this.registerClass[dependency.nameParameter] = aliasTo(
127
+ dependency.nameClassContainer,
128
+ );
129
+ }
130
+ });
131
+ }
132
+
133
+ /**
134
+ * Devuelve las importaciones del módulo.
135
+ * @returns {any[] | undefined} - Importaciones del módulo.
136
+ */
137
+ getImports(): any[] | undefined {
138
+ return this.config.imports;
139
+ }
140
+
141
+ /**
142
+ * Devuelve las clases registradas en el módulo.
143
+ * @returns {any} - Clases registradas.
144
+ */
145
+ getRegisterClass(): any {
146
+ this.logger.debug("Module - register class", this.registerClass);
147
+ return this.registerClass;
148
+ }
149
+ }
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+
package/metadata.d.ts ADDED
@@ -0,0 +1,106 @@
1
+ import { IModuleConfig } from "zanobijs-common";
2
+ /**
3
+ * La clase `Metadata` proporciona métodos para acceder y manipular
4
+ * metadatos relacionados con diversos componentes y módulos.
5
+ */
6
+ export declare class Metadata {
7
+ private static instance;
8
+ private readonly metadataMap;
9
+ private constructor();
10
+ /**
11
+ * Obtiene la instancia única (singleton) de `Metadata`.
12
+ *
13
+ * @returns La instancia única de `Metadata`.
14
+ */
15
+ static getInstance(): Metadata;
16
+ /**
17
+ * Obtiene los metadatos de un módulo específico.
18
+ *
19
+ * @param module - El módulo del cual obtener los metadatos.
20
+ * @returns Un objeto con los metadatos del módulo {imports, controllers ,services, exports }.
21
+ */
22
+ getMetadataModule(module: any): IModuleConfig;
23
+ /**
24
+ * Obtiene todas las dependencias asociadas con una clase.
25
+ *
26
+ * @param target - La función/clase objetivo.
27
+ * @returns Un objeto con las dependencias del target.
28
+ */
29
+ getAllDependencies(target: Function): {
30
+ dClass: any;
31
+ dParam: any;
32
+ dInject: Map<string, string>;
33
+ };
34
+ /**
35
+ * Obtiene las dependencias de clase asociadas con una clase.
36
+ *
37
+ * @param target - La función/clase objetivo.
38
+ * @returns Las dependencias de clase de la clase.
39
+ */
40
+ getClassDependencies(target: Function): any;
41
+ /**
42
+ * Obtiene las dependencias de parámetro asociadas con una clase.
43
+ *
44
+ * @param target - La función/clase objetivo.
45
+ * @returns Las dependencias de parámetro de la clase.
46
+ */
47
+ getParameterDependencies(target: Function): any;
48
+ /**
49
+ * Obtiene las dependencias a inyectar asociadas con una clase.
50
+ *
51
+ * @param target - La función/clase objetivo.
52
+ * @returns Un Map con las dependencias a inyectar de la clase.
53
+ */
54
+ getInjectionDependencies(target: Function): Map<string, string>;
55
+ /**
56
+ * Determina el tipo de una clase basado en sus metadatos.
57
+ *
58
+ * @param target - La función/clase objetivo.
59
+ * @returns Una cadena de texto que indica el tipo del clase segun el mapa de metadata.
60
+ * @throws {Error} Lanza un error si el tipo de la clase es desconocido.
61
+ */
62
+ determineType(target: Function): string;
63
+ /**
64
+ * Verifica si una clase tiene un metadato específico.
65
+ *
66
+ * @param metadataKey - La llave del metadato a verificar.
67
+ * @param target - La función/clase objetivo.
68
+ * @returns Verdadero si el target tiene el metadato, falso en caso contrario.
69
+ */
70
+ private hasMetadata;
71
+ /**
72
+ * Verifica si una clase es de tipo "module".
73
+ *
74
+ * @param target - La función/clase objetivo.
75
+ * @returns Verdadero si el target es de tipo "module", falso en caso contrario.
76
+ */
77
+ isTypeModule(target: Function): boolean;
78
+ /**
79
+ * Verifica si una clase es de tipo "import".
80
+ *
81
+ * @param target - La función/clase objetivo.
82
+ * @returns Verdadero si el target es de tipo "import", falso en caso contrario.
83
+ */
84
+ isTypeImport(target: Function): boolean;
85
+ /**
86
+ * Verifica si una clase es de tipo "controller".
87
+ *
88
+ * @param target - La función/clase objetivo.
89
+ * @returns Verdadero si el target es de tipo "controller", falso en caso contrario.
90
+ */
91
+ isTypeController(target: Function): boolean;
92
+ /**
93
+ * Verifica si una clase es de tipo "service".
94
+ *
95
+ * @param target - La función/clase objetivo.
96
+ * @returns Verdadero si el target es de tipo "service", falso en caso contrario.
97
+ */
98
+ isTypeService(target: Function): boolean;
99
+ /**
100
+ * Verifica si una clase es de tipo "export".
101
+ *
102
+ * @param target - La función/clase objetivo.
103
+ * @returns Verdadero si el target es de tipo "export", falso en caso contrario.
104
+ */
105
+ isTypeExports(target: Function): boolean;
106
+ }