Binary Coffee

Decorator con ES6 y un poquito de inyección de dependencias

javascript nodejs
La imagen que tienen a continuación puede parecer TypeScript, pero no lo es, estamos trabajando con ES6. ![class example](https://api.binary-coffee.dev/uploads/decoractor_example_f7c45d6d9c.png) Esto es posible por medio de los decorators. Para hacer uso de decorators en ES6, podemos utilizar las siguientes librerías: - *@babel/plugin-proposal-decorators*: Permite hacer uso de decorators en el proyecto. - *@babel/plugin-proposal-class-properties*: Se integra con la librería anterior, y facilita el trabajo con los decorators. A continuación voy a explicar como configurar estas dependencias, y continuar mejorando el projecto [Crear un proyecto en Nodejs con Express](https://binary-coffee.dev/post/crear-un-proyecto-en-nodejs-con-express) de la serie: - [Crear un proyecto en Nodejs con Express](https://binary-coffee.dev/post/crear-un-proyecto-en-nodejs-con-express) - [Crear un proyecto en Nodejs con Express 2](https://binary-coffee.dev/post/crear-un-proyecto-en-nodejs-con-express-2) - [Crear un proyecto en Nodejs con Express 3](https://binary-coffee.dev/post/crear-un-proyecto-en-nodejs-con-express-3) # Instalando dependencias y configurando decorators Primeramente instalaremos las dependencias para utilizar los decorators: ``` $ npm install -D @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties ``` Una vez instaladas, ahora pasaremos a la configuración. Primeramente crearemos el archivo de configuraciones *babel.config.json*, quedando de la siguiente manera: ``` { "presets": [ "@babel/preset-env" ], "plugins": [ [ "@babel/plugin-proposal-decorators", {"legacy": true} ], [ "@babel/plugin-proposal-class-properties",{"loose": true} ] ] } ``` Por otra parte, y para los que utilizan eslint, se hace necesario instalar la siguiente dependencia y modificar el archivo de configuración del eslint para que acepte los decorators ``` $ npm install -D babel-eslint ``` ``` // .eslintrc { ... "parserOptions": { ... "ecmaFeatures": { // add these lines "legacyDecorators": true } }, ... } ``` Hecho esto, ya estamos listos para utilizar los decorator. # Utilizando decorators La librería que instalamos anteriormente, permite hacer uso de los decorators de 3 formas distintas: clases, métodos y atributos. A continuación un ejemplo de cada uno. - Clases ``` function MyDecorator(decoratorAttribute) { return function (target) { return class extends target { constructor(...args) { super(...args); this.myDecoratorAttribute = decoratorAttribute; } }; }; } @MyDecorator('example value') class MyClass {} ``` - Métodos ``` function MethodDecorator({parameter}) { return function (target, key, descriptor) { target[key] = (some) => target[key](some, parameter); return descriptor; }; } class MyClass { @MethodDecorator({parameter: 'test'}) method(some, parameter) { ... } } ``` - Atributos ``` function InitialValue(value) { return function (target, key, desc) { desc.initializer = () => { return value; }; }; } class MyClass { @InitialValue('example value') attribute; } ``` De esta manera sencilla, podemos utilizar y crear nuestros propios decorators # Inyección de dependencias Haciendo uso de lo anterior, vamos a crear los archivos necesarios para poder inyectar dependencias en el proyecto. Primeramente vamos a crear el archivo *injection.js*, que es donde vamos a definir todos los decorators necesarios. ``` // injection.js const services = new Map(); export function Injectable() { return function (target) { services.set(target.name, new target()); }; } export function Inject(classObject) { return function (target, key, desc) { desc.initializer = () => { return services.get(classObject.name); }; }; } ``` Cómo se puede apreciar, creamos 2 decorators, uno que permitirá decidir que clases pueden ser inyectadas y otro que permitirá inyectar instancias de estas clases en otras. A continuación un ejemplo de cómo utilizar estos decorators: ``` @Injectable() class UsersService { ... } class UserController { @Inject(UsersService) userService; } ``` De esta manera muy sencilla, ya podemos inyectar clases en otras en sus proyectos. Para ver un poco más cómo pueden utilizar los decorators, les dejo el enlace al proyecto *[Crear un proyecto en Nodejs con Express](https://github.com/dcs-community/nodejs-express-api)* en github. En este proyecto cómo se ve en la imagen del inicio, utilizamos decorators tanto para los controllers cómo para los endpoints de cada controller. # Enlaces de interés - [babel-plugin-proposal-decorators](https://babeljs.io/docs/en/babel-plugin-proposal-decorators) - [Using decorators in JavaScript](https://blog.fullstacktraining.com/using-decorators-in-javascript/) # Conclusiones Si te gustó el artículo, lo viste interesante o simplemente sabes cómo hacerlo mejor, puedes dejar tus comentarios y compartirlo en tus redes sociales. > Happy Coding!!!
Opiniones