MQTT con Deno y Bun no necesita un cliente especial: ambos runtimes ejecutan MQTT.js 5 desde npm, con transportes TCP, TLS y WebSocket, y MQTT.js reconoce Deno explícitamente para usar su build de Node.js. Lo que cambia es cómo se instala, qué permisos concedes, cómo se cargan las variables de entorno y cómo limpian los tests. Esta guía cubre cada runtime, un archivo compartido que funciona en Node.js, Deno y Bun, y las peculiaridades con las que probablemente te encontrarás.
Los ejemplos se conectan a broker.connectmq.com (TCP 1883, TLS 8883, WebSocket seguro 8084 en /mqtt) y usan topics bajo testmqtt/deno-bun/....
Deno: npm specifiers y permisos
Deno puede importar MQTT.js directamente desde npm con un specifier npm:. Sin paso de instalación y, por defecto, sin carpeta node_modules:
@@CODE 0@@
@@CODE 1@@
Deno deniega el acceso a la red y al entorno salvo que lo concedas, algo que encaja muy bien con las herramientas MQTT: el script anterior puede llegar al broker y a nada más. Tres cosas que conviene saber:
- Acceso al entorno desde dependencias. MQTT.js usa el paquete
debug, que inspecciona el entorno. Si Deno te pregunta o se detiene con un error que contieneRequires env access, la petición viene de una dependencia. Amplía a--allow-env(o acepta la pregunta) en lugar de activarlo todo con-A. - Fija la versión mayor.
npm:mqtt@^5mantiene estables los scripts. En proyectos,deno add npm:mqttescribe el mapeo endeno.jsonpara que puedas escribirimport mqtt from "mqtt". - Buffer no es global para tu código. Los payloads son objetos
Bufferde Node.js ypayload.toString()funciona, pero si necesitas el nombre del tipo, impórtalo:import { Buffer } from "node:buffer".
La comprobación de tipos viene incluida. deno check hello.deno.ts usa las declaraciones que trae MQTT.js, así que las opciones de connectAsync y los event handlers quedan totalmente tipados.
Bun: instalar y ejecutar
Bun se comporta de forma muy parecida a Node.js: instalas desde npm y ejecutas TypeScript directamente.
@@CODE 2@@
@@CODE 3@@
@@CODE 4@@
Particularidades de Bun:
.envse carga automáticamente. Bun lee.env(y.env.local,.env.production, …) del directorio de trabajo sin ningún flag. Es práctico paraMQTT_USERyMQTT_PASS, pero también significa que un.envolvidado en la carpeta puede apuntar un script al broker equivocado sin que te enteres.- Sin comprobación de tipos al ejecutar. Bun elimina los tipos y ejecuta. Añade
tsc --noEmit(con@types/bun) a CI si quieres atrapar errores. - La compatibilidad es buena, pero no idéntica. Bun reimplementa
node:net,node:tlsy compañía. Si una conexión se comporta distinto que en Node.js, reprodúcelo con el mismo script en Node antes de culpar al broker; actualizar Bun corrige muchas de estas diferencias.
Un archivo para Node.js, Deno y Bun
Si el proyecto tiene un package.json con mqtt como dependencia, Deno 2 también resuelve los imports sin prefijo a partir de él, así que un único archivo puede ejecutarse en todas partes. Lee la configuración mediante node:process, que ofrecen los tres runtimes:
@@CODE 5@@
@@CODE 6@@
| Node.js | Deno | Bun | |
|---|---|---|---|
| Instalación | npm install mqtt | npm:mqtt@^5 o deno add npm:mqtt | bun add mqtt |
| Permisos | ninguno | --allow-net, --allow-env | ninguno |
Archivos .env | --env-file=.env | --env-file=.env | se cargan solos |
| TypeScript | tsx o type stripping integrado | nativo, deno check | nativo, sin comprobación de tipos |
| Binario único | Node SEA (manual) | deno compile | bun build --compile |
| Tests | Vitest / Jest | deno test | bun test |
El endAsync() del final importa en todos los runtimes: una conexión MQTT abierta mantiene vivo el proceso, así que una CLI que lo olvida nunca termina. Encontrarás más patrones de CLI en crear una herramienta CLI MQTT en Node.js.
Un puente HTTP a MQTT
Ambos runtimes traen un servidor HTTP integrado, lo que reduce un pequeño puente de webhooks a unas pocas líneas. Mantén una conexión MQTT durante toda la vida del proceso y publica en cada petición:
@@CODE 7@@
La versión para Bun cambia dos llamadas:
@@CODE 8@@
Prueba cualquiera de los dos con curl -X POST localhost:8000 -d '{"door":"open"}' mientras el cliente MQTT online está suscrito a testmqtt/deno-bun/#. Para una versión robusta con validación y reintentos, consulta MQTT a webhook.
TLS y WebSockets
mqtts:// en el puerto 8883 funciona en ambos runtimes con certificados de confianza pública. Para un broker con una CA privada:
- Bun acepta la opción
cade MQTT.js igual que Node.js:ca: [readFileSync("ca.pem")]. - Deno usa por defecto su propio almacén raíz. Añade una CA privada con
--cert ca.pem(o la variableDENO_CERT), o defineDENO_TLS_CA_STORE=systempara confiar en el almacén del sistema operativo. Leer el archivo desde el código necesita--allow-read.
Si el puerto 8883 saliente está bloqueado, cambia la URL a wss://broker.connectmq.com:8084/mqtt; nada más cambia en el código. Los errores de certificado se explican en MQTT TLS handshake failed.
Tests: deno test y bun test
Ambos runtimes incluyen un test runner. Un test de ida y vuelta contra un broker real es casi igual en los dos; lo importante es cerrar el cliente en finally:
@@CODE 9@@
Ejecútalo con deno test --allow-net --allow-env. Si olvidas endAsync(), los sanitizers de Deno hacen fallar el test con Leaks detected, algo molesto la primera vez y útil para siempre.
Con Bun, importa test y expect desde bun:test y sustituye la aserción por expect(await received).toBe("ping"). Después ejecuta bun test. Los patrones generales (clientes falsos, timeouts, esperar mensajes) son los mismos que en tests de MQTT.js con Jest y Vitest.
Ver los topics de prueba de Deno y Bun
Distribuir un binario único
Ambos runtimes pueden empaquetar un script, MQTT.js y el propio runtime en un único ejecutable, una forma cómoda de pasar una herramienta de pruebas a tus compañeros sin instalar nada:
@@CODE 10@@
Deno incrusta los permisos en el binario, así que este solo puede llegar al broker que permitiste.
MQTT.js funciona en Deno y Bun con muy pocos cambios: specifiers npm: y permisos explícitos en Deno, carga automática de .env y arranque rápido en Bun. Mantén el código de conexión en un archivo portable, cierra siempre el cliente y prueba el resultado contra un broker real antes de meterlo en un pipeline.
Preguntas frecuentes
¿Existe un cliente MQTT nativo para Deno o Bun?
No te hace falta. Ambos runtimes ejecutan MQTT.js 5 desde npm mediante sus capas de compatibilidad con Node.js, incluidos los transportes TCP, TLS y WebSocket, y MQTT.js detecta Deno explícitamente para usar su build de Node. En Deno se importa con el specifier npm:mqtt; en Bun se instala con bun add mqtt.
¿Qué permisos de Deno necesita un cliente MQTT?
Acceso de red al host del broker (--allow-net=broker.connectmq.com) y acceso al entorno si lees las credenciales de variables. Algunas dependencias también inspeccionan el entorno, así que si Deno muestra "Requires env access", amplía --allow-env. Añade --allow-read solo si cargas archivos de CA desde disco.
¿Por qué falla mi test de Deno con "Leaks detected"?
Los sanitizers de tests de Deno comprueban que cada socket y temporizador abierto durante un test se cierre al terminar. Un cliente MQTT que sigue conectado mantiene abiertos un socket y el temporizador de keep-alive. Llama a await client.endAsync() en un bloque finally para que el test limpie incluso cuando falla una aserción.


