Cómo Publicar tu Dependencia en npm: Guía Completa con TypeScript
Abdiel Martinez |Deja de copiar y pegar código entre proyectos. Aprende a crear y publicar tu propia dependencia en npm paso a paso
¿Cuántas veces has copiado y pegado ese mismo helper de un proyecto a otro? ¿O ese componente de validación que te funciona perfecto y que ya ni te molestas en refactorizar porque "ya está probado"?
Siendo estrictos con el principio de "Don't Repeat Yourself" (DRY), esto es exactamente lo que no deberíamos hacer. Lo ideal sería extraer esa lógica que estás repitiendo de acá para allá y crear una dependencia que puedas instalar en tantos proyectos como quieras. Suena intimidante, lo sé, pero la realidad es que es más sencillo de lo que parece.
Así que en este artículo vamos a explorar cómo publicar una dependencia en npm, usando como ejemplo el siguiente proyecto: epd-wrapper es una dependencia que creé para controlar una pantalla de tinta electrónica. El propósito específico de la dependencia no es lo importante aquí, sino el proceso completo de llevarla desde tu repositorio hasta que cualquiera (incluyendo tu yo del futuro) pueda instalarla con un simple npm install.
Preparando el terreno antes de Publicar
La emoción de "ya tengo el código funcionando, vamos a publicarlo" puede llevarte a publicar algo que técnicamente funciona pero que después te da vergüenza ajena cuando lo ves en npm. Así que antes de apretar el botón de publicar tu dependencia, hay algunas cosas que vale la pena preparar.
La Licencia: Más Importante de lo que crees
Primero que nada, necesitas seleccionar una licencia para tu repositorio. Esto suena aburrido, pero es muy importante. Sin una licencia, técnicamente nadie puede usar tu código legalmente, así que ese paquete que publicaste con tanto cariño... resulta que está en un limbo legal.
Para la mayoría de proyectos open source, MIT o Apache 2.0 funcionan perfecto. GitHub te facilita esto con un selector al crear el repo, pero si ya lo tienes creado, simplemente agrega un archivo LICENSE en la raíz y listo.
El README: Tu Carta de Presentación
Ahora viene la parte que, seamos honestos, es el talón de Aquiles de todo programador: documentar. Pero piénsalo así, ese README no es solo para los demás, es principalmente para tu yo del futuro que dentro de seis meses va a regresar al proyecto sin recordar ni cómo se usa la dependencia.
Puedes usar tu prompt favorito con tu AI de confianza para generar un buen punto de partida. No hay absolutamente ningún problema con eso, solo asegúrate de revisarlo y ajustarlo para que realmente refleje cómo funciona tu dependencia. Tu yo del futuro lo agradecerá cuando esté tratando de recordar qué hacía ese parámetro opcional.
Pero, si prefieres algo más estructurado y no quieres empezar desde cero, existe readme.so, una herramienta que te ayuda a crear tu README con las secciones más comúnmente utilizadas. Te invito a que la explores, tiene una interfaz bastante intuitiva.
Configurando el package.json correctamente
El package.json no es solo ese archivo que npm genera automáticamente, es la carta de identidad de tu dependencia y necesita contener toda la información útil.
Lo básico que definitivamente necesitas configurar: el nombre de tu dependencia, una descripción breve que explique qué hace y tu nombre como autor. Pero hay un par de propiedades más que son de suma importancia y que si las configuras mal, tu dependencia simplemente no va a funcionar.
La propiedad main tiene que apuntar a tu archivo de entrada, ese que exporta todo lo que tu dependencia ofrece. Si estás usando TypeScript y compilando a una carpeta dist, probablemente será algo como "main": "dist/index.js". No vayas a establecer main apuntando a un archivo fuente en TypeScript porque nadie podrá usarla.
Luego está la propiedad types, que apunta a tu archivo de declaraciones de TypeScript (.d.ts). Estos archivos contienen la información de tipos que el editor necesita para darte ese autocompletado y detectar errores antes de ejecutar el código. Si estás usando TypeScript, este lo genera automáticamente cuando haces el build, solo necesitas agregar la siguiente propiedad a tu tsconfig.json:
"declaration": true,
El tsconfig.json completo luciría como el siguiente:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Con "declaration": true" establecido, TypeScript generará automáticamente tus archivos .d.ts junto al código compilado. Luego en tu package.json solo necesitas algo como "types": "dist/index.d.ts".
Las Propiedades que hacen que tu dependencia luzca profesional
Hay otras propiedades que técnicamente son opcionales, pero que hacen una diferencia enorme en cómo se percibe la dependencia. Cuando alguien encuentra tu dependencia en npm y ve que tiene bien configurados los links de repository, bugs y homepage, inmediatamente transmite que te importa el proyecto. Son esas pequeñas señales de que esto no es código abandonado que subiste una vez y nunca volviste a tocar.
La propiedad keywords es especialmente importante porque es lo que ayuda a que la gente encuentre tu dependencia cuando busca soluciones. Piensa en qué términos buscarías tú si necesitaras lo que tu dependencia ofrece. En mi caso del wrapper de la pantalla e-ink, usé keywords como "e-paper", "wrapper", "typescript". Mientras más relevantes y específicos sean tus keywords, mejor.
Decidiendo Qué Subir (y Qué No)
Cuando publicas una dependencia, no quieres subir todo tu repositorio, en parte porque esto aumentaría peso innecesario a la dependencia. En mi caso estoy usando TypeScript, pero a la hora de que alguien instale mi dependencia, lo que se descarga es JavaScript compilado, no mi código fuente en TypeScript.
Por ejemplo no tiene sentido subir mi carpeta src, ni mi node_modules, ni mis archivos de configuración de desarrollo. Lo que realmente quiero publicar es mi carpeta dist que contiene el TypeScript compilado a JavaScript y los archivos de tipos. Otra buena práctica podría ser minificar el contenido antes de subirlo, aunque personalmente no siempre lo hago para dependencias pequeñas.
Pero la pregunta es: ¿cómo le indico a npm qué archivos sí debe incluir?
Hay dos formas principales de hacerlo. La primera es mediante un archivo .npmignore, que funciona como una blacklist donde tachas las carpetas y archivos que no quieres que se suban, por ejemplo la carpeta src, node_modules, archivos de tests, etc. Es similar al .gitignore pero específico para npm.
La segunda forma, que personalmente prefiero porque es más explícita, es mediante la propiedad files en el package.json. Esta funciona como una whitelist donde estableces únicamente los archivos y carpetas que vas a publicar. En el repositorio de ejemplo que estoy usando, lo tengo configurado así:
"files": [
"dist",
"lib",
"README.md",
"LICENSE"
],
Incluyo dist que contiene el JavaScript compilado y el tipado, lib que tiene las librerías de Python a las que les hago el wrapping, el README y la licencia. El package.json no hace falta declararlo porque npm siempre lo incluye automáticamente.
Si usas la propiedad files, no necesitas crear un .npmignore. Queda en ti elegir qué método usar según tus necesidades, pero yo encuentro que con files es más difícil equivocarte y subir algo que no querías.
El Arte de manejar las dependencias
Debemos tener sumo cuidado con qué ponemos en devDependencies y qué en dependencies. ¿Por qué? Porque todo lo que esté en dependencies también se instalará en los proyectos de los usuarios que instalen tu dependencia. En cambio, lo que esté en devDependencies no.
En mi repositorio de ejemplo tengo:
"dependencies": {
"sharp": "^0.33.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0",
"ts-node": "^10.9.0"
}
sharp es una dependencia necesaria para que mi wrapper funcione correctamente, por lo que necesito que siempre se instale. En cambio, ts-node, typescript y @types/node solo son útiles para el desarrollo de la dependencia y definitivamente no deberían instalarse cuando alguien use mi paquete.
peerDependencies 🧐
Aparte de dependencies y devDependencies, existe un tercer tipo que es más avanzado pero vale la pena entender: peerDependencies. Déjame explicarte con un ejemplo.
Imagina que estás creando algún componente de React dentro de tu dependencia. Tu dependencia obviamente depende de que React esté instalado donde se vaya a utilizar. Ahora bien, incluir React dentro de dependencies generaría redundancia porque lo más probable es que el proyecto donde se use tu dependencia ya tenga React instalado, y peor aún, nos podría generar conflictos de versiones entre la que usa el proyecto y la que incluye tu dependencia.
Ahí es donde entran las peerDependencies. La declaración sería así:
{
"peerDependencies": {
"nombre-paquete": "^versión.minima",
"otro-paquete": ">=versión.minima < versión.maxima"
}
}
Cualquier formato de versionado semántico es válido. Cuando alguien instala tu dependencia y esta contiene peerDependencies, sucederá lo siguiente:
npmverifica si la dependencia está instalada al nivel raíz del proyecto.- Si no está instalada, intentará instalar una versión compatible
- Si hay conflictos de versión, mostrará un warning o error dependiendo de la versión de npm.
Espero no haberme complicado mucho con esta explicación. Si tienes alguna duda, déjalo en los comentarios y con gusto lo aclaramos.
Finalmente: Publicando la Dependencia
Teniendo claro todo lo anterior, procedamos a publicarla. Lo primero que necesitamos es tener una cuenta en npm. Si no la tienes, créala en npmjs.com, es gratis para paquetes públicos.
Una vez que tengas tu cuenta, abre tu terminal en la carpeta de tu proyecto y ejecuta npm login. Esto abrirá tu navegador para que inicies sesión o autorices la sesión en la terminal.
Luego sería tan fácil como ejecutar npm publish. Al hacerlo, verás algo como esto en tu terminal:
npm notice
npm notice package: epd-wrapper@1.0.0
npm notice Tarball Contents
npm notice 7.6kB README.md
npm notice 3.5kB dist/index.d.ts
npm notice 2.4kB dist/index.d.ts.map
npm notice 13.7kB dist/index.js
npm notice 10.4kB dist/index.js.map
npm notice 15.3kB lib/epd_bridge.py
npm notice 7.7kB lib/epd.py
npm notice 10.3kB lib/epdconfig.py
npm notice 605B package.json
npm notice Tarball Details
npm notice name: epd-wrapper
npm notice version: 1.0.0
npm notice filename: epd-wrapper-1.0.0.tgz
npm notice package size: 18.2 kB
npm notice unpacked size: 71.6 kB
npm notice shasum: 5799e2cea6cd1be6e9992b20632a1feecdf403de
npm notice integrity: sha512-2lnq7eOTQ7KJR[...]WmLbtQTwg/SXg==
npm notice total files: 9
npm notice
npm notice Publishing to https://registry.npmjs.org/ with tag latest and default access
Authenticate your account at:
https://www.npmjs.com/auth/cli/6b029709-fdff-49ed-b9af-e702a5c5293a
Press ENTER to open in the browser...
Esto te muestra información general de lo que se va a publicar, cuánto pesa el paquete, qué archivos incluye. Es un buen momento para revisar que todo esté como esperabas. Luego te abrirá el navegador mostrando un challenge de autenticación para confirmar que realmente eres tú quien está publicando.

Si todo salió bien, verás en la terminal el nombre de tu dependencia junto con la versión que estableciste en el package.json:
+ epd-wrapper@1.0.0
Y eso es todo. Tu dependencia ahora está disponible de forma publica en npm y cualquiera puede instalarla 🎉
El Caso de los paquetes Scoped
Hay un caso especial que vale la pena mencionar: los paquetes scoped. Si tu dependencia está scoped, por ejemplo @anb98/string-format, notarás que contiene un namespace (en este caso @anb98). Cuando la instalas, aparecerá dentro de una carpeta @anb98 en tus node_modules.
¿Qué utilidad tiene esto? Bueno, varias. Primero, evitas conflictos de nombres con otras dependencias que puedan llamarse igual. Segundo, tienes mejor visibilidad de qué paquetes son tuyos o de tu organización. Y podríamos decir que, en algunos casos, luce más profesional, especialmente si estás publicando bajo el nombre de una empresa.
El scope puede ser tu nombre de usuario de npm o el de una organización. Pero ojo: cuando publicas una dependencia scoped por defecto se publica como privada si tienes una cuenta de pago en npm. Si tienes una cuenta gratuita y tratas de publicar un paquete scoped privado, te dará error. Para publicar un paquete scoped pero público en una cuenta gratuita, necesitas ejecutar:
npm publish --access public
Actualizando Tu Dependencia
Y bueno, eso sería todo para la primera publicación. La siguiente vez que quieras actualizar algo en tu dependencia y publicar una nueva versión, lo que tendrás que hacer es cambiar la versión en tu package.json y simplemente volver a ejecutar npm publish.
Publicar tu primera dependencia en npm es uno de esos hitos que se siente como pasar al "siguiente nivel" como desarrollador. Ya no solo consumes código de otros, ahora también contribuyes al ecosistema. Y aunque parezca intimidante al principio, una vez que lo haces una vez, te das cuenta de lo accesible que realmente es.
Pero, ¿qué pasa cuando necesitas modificar una dependencia que no es tuya? Tal vez encontraste un bug crítico en una librería de terceros que está bloqueando tu proyecto, o necesitas agregar una funcionalidad específica que el mantenedor aún no ha implementado. Si te interesa aprender cómo hacer esto sin romper tu flujo de desarrollo, te invito a leer este artículo donde tratamos justo este punto: Guía Práctica: Cómo Modificar una Dependencia de NPM con yarn patch. Es el complemento perfecto a lo que acabamos de ver aquí.
¿Ya has publicado alguna dependencia en npm? ¿Qué fue lo más complicado que te encontraste en el proceso? Me encantaría escuchar tu experiencia en los comentarios. Y si este artículo te ayudó a publicar tu primera dependencia, ¡cuéntame cómo te fue! 🚀
Articulos relacionados
Transcribe Audios Largos con N8N y FFmpeg sin Límites de Tamaño
Aprende a crear un subworkflow de n8n que segmente y transcriba largos archivos de audio automaticamente
Guía Práctica: Cómo Modificar una Dependencia de NPM con yarn patch
Aprende a tomar el control y parchar node_modules directamente con el comando yarn patch para aplicar arreglos permanentes sin esperar un fix oficial.