mqttjs / MQTT.js

The MQTT client for Node.js and the browser
Other
8.53k stars 1.41k forks source link

Feature Request: Middlewares #1355

Closed MartinMuzatko closed 1 month ago

MartinMuzatko commented 2 years ago

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.

YoDaMa commented 2 years ago

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?

MartinMuzatko commented 2 years ago

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 :)

github-actions[bot] commented 1 year ago

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.

MartinMuzatko commented 1 year ago

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

sibelius commented 1 year ago

we can have this in userland using higher order functions

github-actions[bot] commented 1 month ago

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] commented 1 month ago

This issue was automatically closed due to inactivity.