Crear y publicar paquetes de NestJS en NPM

Claves para poder realizar el proceso de creación de paquetes NPM reusables para el framework NestJS y publicarlos en NPM

Anartz Mugika Ledo🤗
20 min readJan 13, 2023

Este artículo se va a centrar en todo el proceso para del desarrollo / uso de un paquete NPM de NestJS:

  • Aprendemos las bases para crear una librería de NestJS sencilla y manejable para entender los conceptos básicos.
  • Consumirlo y probarlo localmente en una aplicación NestJS.
  • Publicarlo en NPM.

Este artículo sentará las bases para posibles futuros artículos a desarrollo de librerías para NestJs, siempre y cuando tengan buena acogida, profundizando en paquetes de NestJS más complejos.

Seguramente os podáis plantear lo siguiente, ¿por qué crear una librería?

Es simple, imaginaros que trabajáis en varios proyectos que son diferentes pero que tienen funcionalidades iguales, es decir, que son lo mismo línea a línea y en modo de usar.

Un buen ejemplo podría ser un sistema de gestión de usuarios con su login, registro, reset de contraseña,…

Podréis decirme que se puede copiar y pegar a la antigua usanza, pero eso os asegura que conlleva a una cola de posibles problemas y quebraderos de cabeza que mejor evitarlos, no merece la pena. ¿O si? Personalmente prefiero centrarme en lo importante y no en lidiar problemas que se pueden evitar aplicando buenas prácticas.

Con la librería, podremos gestionar diferentes versiones, actualizar a nuevas versiones fácilmente proyecto a proyecto con un comando y con los cambios a la adaptaciones a realizar.

Ahora que ya tenemos claro la razón por la centrarse en una librería, vamos a por ello, pasando por los requisitos iniciales a tener en cuenta.

Requisitos mínimos para poder trabajar en este artículo

  • Cuenta de NPM (os podéis registrar desde aquí)
  • Conocimientos básicos de NestJS (con haber trabajado en las bases más que suficiente)
  • CLI de NestJS instalado
  • Ganas de aprender y posteriormente experimentar con lo aprendido en implementaciones propias (HIPER RECOMENDADO)

Vale, ya tenemos lo necesario para empezar. ¡¡Comencemos!!

Preparativos hasta empezar a trabajar con la librería

Antes de crear la librería, necesitamos crear la base del proyecto donde vamos a trabajar con la aplicación y donde tendremos el proyecto de la librería, como se realiza en Angular.

Primero creamos el proyecto ejecutando el siguiente comando:

nest new <projectName> --package-manager [options: npm, yarn, pnpm]

En nuestro caso, seleccionaremos la siguiente información con el gestor de dependencias de NPM aunque esto es elección de cada persona optar por lo que mejor le viene:

nest new app-library --package-manager npm

Y este será el proceso de crear el proyecto:

Como ha ido todo bien, seguimos las instrucciones para arrancar el proyecto, accedemos a la carpeta del proyecto y ejecutamos npm run start

Una vez ejecutado debe de mostrarse un mensaje similar:

Con esto ya tenemos la app en marcha y accedemos a la siguiente URL que es la que se usa por defecto, con el puerto 3000 mediante la url que podéis ver en la imagen:

Ahora vamos a lo bueno, a crear el proyecto de la librería para poder realizar los pasos, ¡¡¡hasta desplegarlo en NPM!!!

Crear la estructura de la librería

Vamos a comenzar con el desarrollo de la librería y lo haremos siguiendo las instrucciones correspondientes a la documentación oficial relacionadas al tema del desarrollo y conceptos de librerías. Accedemos y os recomiendo que almacenéis esta dirección en favoritos, para usar dicha referencia en el futuro cuando estéis trabajando con el desarrollo de librerías.

Ejecutamos el comando para generar un proyecto de librería dentro del proyecto donde estamos trabajando actualmente:

nest generate library <LIBRARY_NAME>
nest g library <LIBRARY_NAME>
nest g lib <LIBRARY_NAME>

Donde <LIBRARY_NAME> será el nombre de la librería. Nosotros le llamamos por ejemplo my-hello-library ejecutando el siguiente comando (podemos hacerlo de cualquiera de la tres formas mostradas):

nest generate library my-hello-library

Una vez ejecutado, cuando procese la orden, nos aparecerá lo siguiente en la consola:

¿Qué quiere decir esto? Esto es para asignar el prefijo que vamos a usar para consumir la librería dentro del proyecto y así poder consumirla mediante los alias haciendo uso de los paths (rutas) absolutos tal y como se realiza en Angular. Por defecto nos sugieren que usemos @app y vamos a seguir esa sugerencia ejecutando INTRO.\

Una vez aceptada esa sugerencia, procede a crear el proyecto de librería dentro de un nuevo directorio principal llamado libs (1) que contendrá nuestra librería ( y todas las que creemos bajo el comando ng g lib...) y actualizará los ficheros (2):

La estructura de la librería la podemos encontrar de la siguiente manera, que la veremos con más detalle posteriormente:

Ahora nos centramos en los cambios realizados en los ficheros del proyecto principal que se da en lo siguientes ficheros:

nest-cli.json

Se añade la información de la metadata correspondiente a la librería que hemos creado ahora mismo. En el fichero, dentro de projects se añade un nuevo objeto con la información principal del proyecto que en este caso es la nueva librería creada. Habrá dos diferencias principales en el fichero nest-cli.json entre lo que son las librerías y las aplicaciones:

  • La propiedad type se asigna con el valor library en vez de application cuando se da esta situación de que lo que se está implementando es una librería.
  • La propiedad entryFile (fichero por donde accede al código de esa implementación) será index en vez de main

Estas diferencias son importantes tenerlas en cuenta, para que el proceso de compilación a la hora de manejar las bibliotecas sea de la manera correcta.

Por ejemplo, una biblioteca exporta sus funciones a través del archivo index.ts. Al igual que con los proyectos de tipo aplicación, cada biblioteca tiene su propio archivo tsconfig.lib.json que amplía el archivo tsconfig.json raíz (en todo el monorepo).

tsconfig.json

En este fichero que contiene la configuración de Typescript del proyecto principal, se añaden los paths para poder acceder a la librería mediante un alias, sin necesidad de trabajar con rutas relativas (veremos al aplicar el ejemplo, con rutas relativas y mediante el uso de paths absolutos). Lo que se añade es lo siguiente:

"paths": {
"@app/my-hello-library": [
"libs/my-hello-library/src"
],
"@app/my-library/*": [
"libs/my-hello-library/src/*"
]
}

Quedando de la siguiente forma:

Con esto podremos acceder por ejemplo al fichero index.ts de una manera más sencilla, haciendo uso de paths absolutos.

package.json

Realizará cambios en el script format con el objetivo de darle formato con prettier para estar todo según las reglas establecidas y cambiará la propiedad rootDir de “src” a “.” ya que ahora entra en juego el código en el directorio libs donde ya tendremos código.

Añade la referencia mapeada del módulo para poder acceder a el mediante los paths.

test/jest-e2e.json

Cambios relacionados a añadir las referencias mapeadas de la librería para poder especificar los test e2e en el código correspondiente a la librería.

Estos son los cambios significativos en este proyecto. Seguimos con el apartado para saber como consumir esta librería en local.

Consumir la librería y realizar cambios

Antes de empezar con la parte de consumir la librería, vamos a realizar un ligero cambio en el servicio de la librería, para personalizarlo un poco.

Vamos a libs/my-hello-library/src/my-hello-library.service.ts y cambiamos de este código:

import { Injectable } from '@nestjs/common';

@Injectable()
export class MyHelloLibraryService {}

Al siguiente:

import { Injectable } from '@nestjs/common';
@Injectable()
export class MyHelloLibraryService {
basic = () => console.log('Basic hello');
}

Con esto ya tenemos un mínimo para poder observar la información al consumirlo desde el proyecto principal.

Ahora si, para poder consumir la librería tenemos que obtener la referencia del módulo principal si queremos usar todas las funcionalidades que acoplamos a ella mediante imports.

También tenemos añadida la referencia del servicio que podremos usarlo individualmente si solo deseamos usar ese servicio añadiéndolo en providers del módulo que queremos acoplarlo.

Estos son conceptos básicos que deberíamos de conocer para trabajar con este artículo, por lo que ya no me voy a extender.

Estas referencias están definidas en el fichero de entrada index.ts dentro de libs/my-hello-library/src.

libs/my-hello-library/src/index.ts

export * from './my-hello-library.module';
export * from './my-hello-library.service';

Si vamos a consumirlo en app.module.ts lo hacemos de las siguientes formas:

  • Si queremos usar el servicio únicamente acoplándolo en el controlador
import { MyHelloLibraryService } from '@app/my-hello-library';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
imports: [],
controllers: [AppController],
providers: [AppService, MyHelloLibraryService],
})
export class AppModule {}
  • Si queremos usar las funcionalidades que se han añadido dentro del módulo de la librería (controladores, servicios,…)
import { MyHelloLibraryModule } from '@app/my-hello-library';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
imports: [MyHelloLibraryModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Añadiendo la inyección dentro de app.controller.ts (Será igual en los dos casos por querer usar solo el servicio que es lo que tenemos):

import { MyHelloLibraryService } from '@app/my-hello-library';
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
constructor(private readonly appService: AppService, private readonly myHelloLibrary: MyHelloLibraryService) {}
@Get()
getHello(): string {
this.myHelloLibrary.basic();
return this.appService.getHello();
}
}

Ahora ejecutando npm start iniciamos la ejecución de nuestro proyecto y si todo va bien debería de darse un mensaje similar a este en la consola:

Y si ejecutamos la url: http://localhost:3000/

Por cada ejecución que realizaremos aparecerá Basic Hello

Como se puede ver, en mi caso como he ejecutado dos veces la url mencionada, aparece Basic Hello dos veces.

Viendo esto último, ya sabemos consumir funcionalidades como un servicio dentro del proyecto principal.

Si os fijáis, la importancia de hacer uso del path @app/my-hello-library para poder hacer uso del servicio y/o módulo. Es algo a tener en cuenta cuando estemos trabajando EN DESARROLLO.

Con esto, finalizaríamos el desarrollo de nuestro paquete y lo tendríamos ya para publicarlo en NPM después de unos ajustes que veremos a continuación.

Configurar librería para subirlo a NPM

Antes de poder compilar nuestro paquete y enviarlo a NPM o usarlo como un paquete local, debemos de añadir el fichero de manifiesto con la información principal del paquete.

Al ejecutar dicho comando se empaquetará el proyecto de librería para poder consumirlo e incluso usarlo dentro de este proyecto pero no para poder publicarlo ya que es necesario si o si un fichero de manifiesto, que es el package.json (que lo vamos a crear ahora) donde se almacenarán los datos del nombre de paquete, versión y dependencias almacenadas, esto es fundamental para poder publicarlo, sin ello, imposible.

Para crear este fichero, navegamos al directorio efectuamos los siguientes pasos:

cd libs/my-hello-library/
npm init -y

Con estas ordenes primero accedemos al directorio de la librería y posteriormente creamos el fichero de manifiesto package.json de nuestro proyecto de librería cuya información será la siguiente:

{
"name": "my-hello-library", (1)
"version": "1.0.0", (2)
"description": "", (3)
"main": "index.js", (4)
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}, (5)
"keywords": [], (6)
"author": "", (7)
"license": "ISC" (8)
}
  • (1) Nombre del paquete. Este valor es fundamental para cuando publiquemos, por el momento no le damos más importancia y lo mantenemos.
  • (2) Versionado semántico: Fundamental como el nombre del paquete, estos dos primeros valores son obligatorios y sin ellos no podemos publicar nada, por lo que hay que añadirlos. ¿Y qué es el versionado? Más información la tenéis a continuación.
  • (3) Descripción: Como bien indica es la descripción que queramos indicarle al proyecto, no es fundamental ni es obligatorio, pero puede ser una buena referencia.
  • (4) Fichero de entrada de la librería, si no ponemos por defecto será index.js y este será generalmente el fichero de entrada.
  • (5) scripts: Apartado para definir diferentes scripts dentro de la librería. Esto lo quitaremos ya que no nos resulta útil.
  • (6) keywords: Palabras clave para que podamos buscar mejor la librería cuando se suba a NPM. Esto si lo tenemos en cuenta para intentar añadir las palabras clave más adecuadas y posicionar mejor nuestra librería en el repositorio de NPM.
  • (7) author: Información del autor de la librería añadiendo su nombre, email y url (no son obligatorios pero si recomendables añadirlo)
  • (8) license: Licencia que usaremos para nuestra librería.

Teniendo en cuenta esto, como referencia yo os propongo dejarlo de esta manera para complementar el mínimo donde explicaré los puntos que se han añadido / modificado:

{
"name": "my-hello-library", (1)
"version": "1.0.0", (2)
"description": "Our first NestJS library", (3)
"main": "index.js", (4)
"keywords": ["nestjs", "hello", "learn-nestjs"], (5)
"author": { (6)
"name": "Anartz Mugika Ledo",
"email": "mugan86@gmail.com",
"url": "https://mugan86.medium.com/"
},
"license": "MIT", (7)
"peerDependencies": { (8)
"@nestjs/common": "^9.0.0",
"@nestjs/core": "^9.0.0"
}
}

Detallando más parte a parte lo añadido / modificado:

  • (1) Sin cambios en el nombre de paquete, por el momento. Quizás hay que modificar el valor de este si existe en el repositorio de NPM, por lo que luego lo comprobaremos al querer efectuar el último paso antes de publicar la librería.
  • (2) Versionado semántico: Definimos como 1.0.0 y posteriormente añadiremos las versiones en base a lo que se describe aquí para seguir buenas prácticas de versionado.
  • (3) Descripción: Describimos lo que va a hacer la librería, es opcional.
  • (4) Fichero de entrada, sin cambios.
  • (5) Palabras clave añadidas.
  • (6) Información acerca del autor de la librería.
  • (7) Licencia MIT. ¿Por qué esta licencia y no otras? La definición de la licencia es algo que hay que mirar con tranquilidad pero si no queremos poner muchas trabas ni que haya quebraderos de cabeza pensando en si "nos roban el código ó no", esta es la más adecuada ya que permite reutilizar el software así licenciado tanto para ser software libre como para ser software no libre, permitiendo no liberar los cambios realizados al programa original.
  • (8) peerDependencies: conocidas en Español como dependencias de pares. Este valor sirve para dar constancia de todos los paquetes que se requieren exactamente en el proyecto o para la persona que está descargando y los números de versión también deben ser los mismos. Esa es la razón por la que han sido nombrados como peerDependencies. El mejor ejemplo es ‘reaccionar’, que es común en todos los proyectos para ejecutarse de manera similar.
  • Nota: Estas dependencias no se instalan automáticamente. npm nos muestra un mensaje de advertencia cada vez que hay una Dependencia de pares y estas son dependencias diferentes (en versiones) en comparación con las dependencias que se están asignando en este valor.

Ahora lo que nos queda es crearnos los ficheros README.md y LICENSE.md para tener los ficheros que van a ser super útiles (NO SON OBLIGATORIOS pero si recomendables) para hacer la librería más completa con sus instrucciones y la licencia a usar.

En el README.md añadimos los siguiente, esto será un mínimo:

# My Hello NestJS Library

Nest Library to learn how to create and publish libraries in NPM.
## Instructions
### Install
```npm install my-hello-library```
### Use library
... Define instructions to consume library

LICENSE.md

Usaremos la plantilla de la licencia MIT

Copyright <AÑO> <AUTOR>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Siendo en mi caso:

Copyright 2023 Anartz Mugika
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Con todos estos cambios ya tenemos la estructura necesaria y válida para poder considerar como candidato a publicarse nuestra librería en el repositorio NPM.

La estructura de ficheros será la siguiente después de todos estos cambios:

Compilando librería

Para poder compilar la librería, añadimos el siguiente script:

"build:lib": "rimraf dist && tsc -p ./libs/my-hello-library/tsconfig.lib.json",

Lo ejecutamos:

npm run build:lib

Y el resultado generado se añadirá dentro de la carpeta dist

Al analizar dicho resultado nos damos cuenta que faltan los 3 ficheros que hemos creado en el paso anterior, uno de ellos fundamentales para poder publicar la librería. ¿Qué fichero es? El fichero package.json.

Al compilar la librería, añadirá todo lo que sea Typescript y en nuestro caso estamos con varios ficheros como el fichero package.json, README.md y LICENSE.md que no se añadirán en el resultado.

Para poder añadirlo, deberemos de hacer una copia del directorio original al generado a la hora de compilar la librería. Lo haremos con los tres y para ejecutar de una manera ordenada, creamos un fichero para ejecutar comando Linux dentro del proyecto:

touch copy-libraries-files.sh

Y dentro de este añadimos la siguiente información:

cp ./libs/my-hello-library/package.json ./dist/libs/my-hello-library
cp ./libs/my-hello-library/README.md ./dist/libs/my-hello-library
cp ./libs/my-hello-library/LICENSE.md ./dist/libs/my-hello-library

Podemos probar a ejecutar individualmente el fichero mediante

sh copy-libraries-files.sh

Debería de copiar esos 3 ficheros (tener en cuenta que ya debería de estar ejecutado el comando para compilar la librería y debe de existir el directorio dist/my...).

Deberían de aparecer como en la siguiente imagen teniendo añadidos los 3 ficheros “rebeldes”.

¡Bien! Ahora vamos a añadir esa orden dentro del script a lo anterior, quedando de la siguiente manera:

"build:lib": "rimraf dist && tsc -p ./libs/my-hello-library/tsconfig.lib.json && sh copy-libraries-files.sh",

Con esto ya podremos compilar la librería al completo con toda la información necesaria junto con los ficheros opcionales como la licencia y el README.md que servirán para darle un plus de seriedad a la librería mostrando sobre todo con el README.md los pasos que habrá que dar para poder trabajar con dicha librería.

Publicar el paquete

Ahora estamos listos para publicar nuestro paquete recién creado y configurado. Para completar este paso, vamos a necesitar disponer de una cuenta gratuita en www.npmjs.com. Si no disponemos de cuenta, debemos de acceder al apartado para registrar nuestra cuenta.

Aspectos a tener en cuenta a la hora de publicar un paquete en NPM

Todos los paquetes npm tienen un nombre. ¿Cómo añadir el nombre de un paquete? ¿Qué tenemos que tener en cuenta? Toda la información de las reglas a seguir para trabajar con los nombres de los paquetes a continuación.

¿Cómo saber si el nombre de nuestro paquete no existe en NPM? Es más sencillo de lo que parece descubrirlo. Vamos a NPM y cogiendo el nombre del paquete lo añadimos en la url siguiendo esta estructura:

https://www.npmjs.com/package/<package-name>

Vamos a imaginar que el nombre de nuestro paquete es @angular/cli (podéis probar con alguno que sabéis que existe) por lo que para probarlo, deberíamos de intentar acceder a esta url:

https://www.npmjs.com/package/@angular/cli

Si existe (en este caso es evidente que lo es) debe de aparecer la información de ese paquete con su README.md, información básica del paquete y etc, algo como lo siguiente:

¿Cómo saber si nuestro nombre de paquete no está cogido?

Es seguir el mismo proceso, pero en vez de añadir la referencia del CLI de Angular, cogemos el nombre del paquete asignado al fichero de manifiesto package.json cuyo valor es

my-hello-library

Y la url del paquete publicado debería de ser la siguiente:

https://www.npmjs.com/package/my-hello-library

Accediendo a esa url dando este resultado:

Podemos asegurar que el nombre ya está cogido por otra persona ya que no nos da un error 404 (lo veremos a continuación para identificarlo). ¿Cómo hacer para que usando ese nombre podamos publicarlo?

Un consejo es añadir delante del nombre de paquete vuestro usuario de NPM, formando lo siguiente:

@<usuario npm>/my-hello-library

El uso de añadirle un @ y el usuario de nuestra cuenta de NPM se denominan los nombres con ámbito que son útiles para crear un espacio de nombres único para nuestros paquetes. Si tú y yo publicamos my-hello-library en npmjs.org, habrá una colisión como es el caso actual en el que hemos hecho la prueba.

Por esa razón, siendo mi usuario mugan86 sería:

@mugan86/my-hello-library

Formando la url:

https://www.npmjs.com/package/@mugan86/my-hello-library

Accediendo a esa url podemos comprobar que no existe ese paquete y que podríamos publicarlo con ese nombre.

Por lo tanto, lo cambiamos de lo que tenemos:

{
"name": "my-hello-library",
...
}

A lo siguiente:

{
"name": "@mugan86/my-hello-library",
...
}

Con esto ya tendremos definido correctamente un nombre que no existe en el repositorio de NPM publicado (Hay que tener en cuenta que si usáis este mismo nombre cuando este el artículo publicado, que no va a estar disponible. Añadid vuestro usuario en vez de mugan86 para evitar este conflicto mencionado ahora mismo).

Paquetes de NPM públicos: npm nos permite publicar paquetes de forma gratuita siempre que sean públicos. Si hacemos uso del usuario con ámbito (añadiendo @<usuario>) lo va a considerar un paquete privado y a menos que lo configuremos para que sea visible, no podremos publicarlo. Lo configuraremos antes de publicarlo de tal manera.

Hay una opción que si desea publicar paquetes privados (por ejemplo, para compartir solo dentro de nuestra empresa), necesitando una cuenta privada y debiendo pagar por ese servicio. Alternativamente, podemos configurar un registro privado interno con un servidor de registro como Verdaccio.

Teniendo en cuenta estos detalles vamos a proceder con la publicación de nuestro paquete NestJS desarrollado en este artículo.

Publicar paquete en NPM

Para publicar el paquete debemos de navegar al directorio dist/libs/my-hello-library (hay que tener compilado el proyecto) y desde dentro de la información compilada debemos de ejecutar el comando para publicar que será.

Añadimos el script para que navegue directamente a ese directorio y si este no existe, ya nos dará un error y sabremos que hay que compilarlo. Si existe, accede y ejecuta el comando para publicar mediante npm publish. Lo definimos de la siguiente manera y lo ejecutamos con npm run publish:lib:

"publish:lib": "cd dist/libs/my-hello-library && npm publish"

¿Cómo soluciona el problema? Siguiendo las indicaciones de esta URL nos percatamos que tenemos que habilitar el paquete con acceso público mediante --access public

Teniendo en cuenta ese detalle, modificamos el script a lo siguiente:

"publish:lib": "cd dist/libs/my-hello-library && npm publish --access public"

Ejecutar de nuevo, y como se puede ver el proceso se ejecuta correctamente, sin ningún problema:

  • (1) Ejecuta el comando para acceder al directorio donde esta la librería compilada y el comando para publicar. Posteriormente efectua el empaquetado para enviarlo al repositorio.
  • (2) Como todo va bien, ya está habilitado para añadirlo de manera pública, se publica sin problemas.

Una vez publicado, debemos de acceder a la la página principal de nuestro paquete en la siguiente url con este formato (como se ha visto para ver la disponibilidad del paquete):

https://www.npmjs.com/package/<NOMBRE_PAQUETE>
NOMBRE_PAQUETE = @mugan86/my-hello-library

Construyendo la Url completa, sería esta:

https://www.npmjs.com/package/@mugan86/my-hello-library

Accediendo a ella nos encontramos con esta página con todos sus datos:

1.- Url del paquete

2.- Nombre del paquete

3.- Información definida en el README.md

4.- Número de version

5.- Tipo de Licencia.

Con esto ya tenemos lo más dificil completado, ahora queda probarla instalando en nuestro proyecto con lo que hemos subido.

Consumir librería publicada en proyecto

Para poder consumir la librería recien publicada debemos de ejecutar el siguiente comando:

npm install @mugan86/my-hello-library

Una vez que la instalemos debemos de cambiar la referencia @app/my-hello-library tanto en el fichero app.module.ts y app.controller.ts, para consumir la librería correctamente.

Vamos a app.module.ts y eliminamos el import, a la hora de importar nos sugiere las dos opciones, la del desarrollo y la del paquete instalado, obviamente en este caso vamos a por la del paquete instalado, cogiendo la primera opción:

El código quedará de la siguiente manera para app.module.ts

import { MyHelloLibraryModule } from '@mugan86/my-hello-library';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
imports: [MyHelloLibraryModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

Ahora lo que nos queda es implementar este cambio también en app.controller.ts haciendo la misma jugada pero en vez de importar el módulo, lo haremos con el servicio.

Pasando de esto:

import { MyHelloLibraryService } from '@app/my-hello-library'; // <===
...
@Controller()
export class AppController {
....
}

A lo siguiente:

import { MyHelloLibraryService } from '@mugan86/my-hello-library'; // <===
...
@Controller()
export class AppController {
....
}

Ahora lo que nos queda es ejecutar el comando npm start para ver que todo funciona correctamente haciendo uso de la librería desarrollada y publicada en NPM.

Al iniciar se debe de ver como antes, sin ningún error:

Si accedemos a la API a la siguiente URL

Debe de mostrarse el mensaje Hello World en el navegador y Basic Hello en la consola, mensaje que se ha añadido en el servicio de la librería

Conclusión

Llegados a este punto sabemos el proceso detallado para crear librerías en NestJS y como publicarlas.

Lo que nos faltaría es darle más mimo al apartado de las instrucciones que se redactan en el README.md para que cualquier persona que consuma nuestra librería pueda hacerlo sin problemas.

En futuros artículos, nos centraremos en el desarrollo de una librería sencilla (en NestJS, Angular o la tecnología que sea, seguramente en Typescript para generalizarlo más) en el que se cubrirán TODOS los aspectos de manera minuciosa.

Estaros atentos (y seguidme (1), aparte de suscribiros a mi newsletter (2) con un aviso por cada artículo escrito, ni más ni menos) que ese artículo va a ser super interesante y útil.

Si queréis aprender a crear librerías NPM de manera super detallada desde las bases y paso a paso os animo a que obtengáis mi curso de NPM

Código de lo desarrollado:

Presencia en redes sociales

Podéis encontrarme en las siguientes redes.

--

--

Anartz Mugika Ledo🤗
Anartz Mugika Ledo🤗

Written by Anartz Mugika Ledo🤗

[{#frontend:[#mobile:{#android, #kotlin, #ionic}}, {#web:{#angular, #qwik, #bootstrap}}],{#backend: [{#graphql, #nestjs,#express, #mongodb, #mysql}]}]

Responses (1)