MQTT.js icon indicating copy to clipboard operation
MQTT.js copied to clipboard

Feature Request: Middlewares

Open MartinMuzatko opened this issue 2 years ago • 5 comments

Hello!

I'd like to propose a feature that would help to transform subscribe and publish messages, to support e.g. different data formats like JSON as a configuration. Similar to how express or axios is handling request transforms/middlewares, it would be great to be able to set middlewares for mqtt.

import * as mqtt from 'mqtt'
mqtt.connect('mqtt://localhost:1883', {
    middlewares: [
        (topic, message, type) => ({ topic, message: type == 'receive' ? JSON.parse(message) : JSON.stringify(message) })
    ]
})

This would enable me to use JSON or any other format I'm encoding/decoding to. Beyond that, I'd see many more possible benefits from this feature. Like a topic translator, forwarder, rate limiting (throttling/debouncing), etc.

What are the alternatives?

Option 1: Wrap mqtt.connect function

It is possible to wrap mqtt.connect to return an MQTTClient with similar interface like so:

const connect = (brokerUrl?: string | any, opts?: IClientOptions) => {
    const client = mqtt.connect(brokerUrl, opts)
    return {
        ...client,
        publish: (topic: string, message: any) => client.publish(topic, JSON.stringify(message)),
        on: (name: string, callback) => client.on(name, (topic, message) => callback(topic, JSON.stringify(message)))
    }
}

It would take extra effort and boilerplate to support the variants of publish and subscribe. I am also uncertain whether we would lose prototype and special symbols when spreading the client into a regular object.

Option 2: Wrap publish and on function directly

const publish = (topic: string, message: any) => mqtt.publish(topic, JSON.stringify(message))
const onData = <T>(cb) => mqtt.on('data', (topic, message) => cb(topic, JSON.parse(message) as T))

This gives us a little more flexibility. If we want to re-use this for other clients, we might also inject mqtt as dependency via function parameters. Enforcing this as a practice across a bigger repository seems hard though. It would be better to modify the existing client to not hinder access to other important features.

What are your thoughts? Are there existing npm modules that wrap mqtt to allow middlewares or specificially JSON as the default message data format?

Glad to read your opinions.

MartinMuzatko avatar Nov 18 '21 10:11 MartinMuzatko

Hi @MartinMuzatko, I like the idea of a middleware for handling different datastructures. Only problem is it would need to be maintained and I assume would be a separate package from the mqtt package. Would you be up for working on it?

YoDaMa avatar Dec 27 '21 20:12 YoDaMa

Hello @YoDaMa ! If there was sufficient plugin/extension support for mqttjs to create such a plugin, I'd be in for building and maintaining it :)

MartinMuzatko avatar Dec 28 '21 08:12 MartinMuzatko

This is an automated message to let you know that this issue has gone 365 days without any activity. In order to ensure that we work on issues that still matter, this issue will be closed in 14 days.

If this issue is still important, you can simply comment with a "bump" to keep it open.

Thank you for your contribution.

github-actions[bot] avatar Dec 29 '22 02:12 github-actions[bot]

What is the status, is there a possibility to extend mqtt in such a way to write plugins such as a json parse middleware?

MartinMuzatko avatar Jan 02 '23 15:01 MartinMuzatko

we can have this in userland using higher order functions

sibelius avatar Jul 21 '23 14:07 sibelius