UNPKG

@robot.com/better-mqtt

Version:

A modern, TypeScript-first MQTT client library that provides a better developer experience with async iterators, shared subscriptions, and React hooks. Better MQTT is a wrapper around the excellent [mqtt.js](https://github.com/mqttjs/MQTT.js) library, enh

1 lines 28.5 kB
{"version":3,"sources":["../src/index.ts","../src/match.ts","../src/subs-manager.ts","../src/subscription.ts","../src/generator.ts"],"sourcesContent":["/** biome-ignore-all lint/suspicious/noExplicitAny: I'm sure it is fine */\nimport { EventEmitter } from 'ee-ts'\nimport mqtt, {\n type ErrorWithReasonCode,\n type IClientOptions,\n type MqttClient,\n} from 'mqtt'\nimport { SubscriptionManager } from './subs-manager'\nimport { Subscription } from './subscription'\nimport type { SubscriptionOptions } from './types'\n\nexport * from './subscription'\nexport * from './types'\n\nexport type ConnectArgs =\n | [brokerUrl: string]\n | [brokerUrl: string, opts?: IClientOptions]\n | [opts: IClientOptions]\n\nexport interface BetterMQTTEvents {\n status(status: 'online' | 'offline'): void\n error(error: Error | ErrorWithReasonCode): void\n end(): void\n}\n\nexport type MessageParser<T = string> = (message: Buffer) => T\n\nexport function stringParser(message: Buffer): string {\n return message.toString('utf8')\n}\n\nexport function jsonParser<T = unknown>(message: Buffer): T {\n return JSON.parse(message.toString('utf8'))\n}\n\nexport function binaryParser(message: Buffer): Buffer {\n return message\n}\n\nexport class BetterMQTT extends EventEmitter<BetterMQTTEvents> {\n readonly client: MqttClient\n error: Error | ErrorWithReasonCode | null = null\n\n get status() {\n return this.client.connected ? 'online' : 'offline'\n }\n\n private subscriptions: SubscriptionManager = new SubscriptionManager()\n\n constructor(client: MqttClient) {\n super()\n\n this.client = client\n this.client.on('offline', () => {\n this.emit('status', 'offline')\n })\n\n this.client.on('connect', () => {\n this.emit('status', 'online')\n })\n\n this.client.on('connect', () => {\n this.emit('status', 'online')\n })\n\n this.client.on('error', (error) => {\n this.error = error\n this.emit('error', error)\n })\n\n this.client.off('end', () => {\n this.end(false)\n })\n\n this.client.on('message', (topic, message, packet) => {\n this.subscriptions.handleMessage(topic, message, packet)\n })\n }\n\n publish(\n topic: string,\n message: string | Buffer,\n opts?: { qos?: 0 | 1 | 2; dup?: boolean; retain?: boolean },\n ) {\n this.client.publish(topic, message, {\n qos: opts?.qos ?? 2,\n dup: opts?.dup,\n retain: opts?.retain,\n })\n }\n\n async publishAsync(\n topic: string,\n message: string | Buffer,\n opts?: { qos?: 0 | 1 | 2; dup?: boolean; retain?: boolean },\n ): Promise<void> {\n await this.client.publishAsync(topic, message, {\n qos: opts?.qos ?? 2,\n dup: opts?.dup,\n retain: opts?.retain,\n })\n }\n\n publishJson<T>(topic: string, message: T) {\n this.publish(topic, JSON.stringify(message))\n }\n\n async publishJsonAsync<T>(topic: string, message: T): Promise<void> {\n await this.publishAsync(topic, JSON.stringify(message))\n }\n\n unsubscribe(sub: Subscription<unknown>) {\n sub.emit('end')\n const group = this.subscriptions.remove(sub)\n if (group?.isEmpty()) {\n this.client.unsubscribe(group.topic)\n }\n }\n\n subscribe<T>(\n topic: string,\n parser: MessageParser<T>,\n options?: Partial<SubscriptionOptions>,\n ): Subscription<T> {\n const sub = new Subscription<T>({ mqtt: this, topic, parser, options })\n\n const { resubscribe, group } = this.subscriptions.add(sub)\n\n if (resubscribe) {\n this.client.subscribe(sub.topic, {\n qos: sub.options.qos,\n rh: sub.options.rh,\n rap: sub.options.rap,\n nl: sub.options.nl,\n properties: {\n subscriptionIdentifier: group.id,\n },\n })\n }\n\n return sub\n }\n\n subscribeString(\n topic: string,\n options?: Partial<SubscriptionOptions>,\n ): Subscription<string> {\n return this.subscribe(topic, stringParser, options)\n }\n\n subscribeJson<T>(\n topic: string,\n options?: Partial<SubscriptionOptions>,\n ): Subscription<T> {\n return this.subscribe<T>(topic, jsonParser, options)\n }\n\n // TODO: Subscribe zod\n\n subscribeBinary(\n topic: string,\n options?: Partial<SubscriptionOptions>,\n ): Subscription<Buffer> {\n return this.subscribe(topic, binaryParser, options)\n }\n\n async unsubscribeAsync(sub: Subscription<unknown>) {\n sub.emit('end')\n const group = this.subscriptions.remove(sub)\n if (group?.isEmpty()) {\n await this.client.unsubscribeAsync(group.topic)\n }\n }\n\n async subscribeAsync<T>(\n topic: string,\n parser: MessageParser<T>,\n options?: Partial<SubscriptionOptions>,\n ): Promise<Subscription<T>> {\n const sub = new Subscription<T>({ mqtt: this, topic, parser, options })\n\n const { resubscribe, group } = this.subscriptions.add(sub)\n\n if (resubscribe) {\n await this.client.subscribeAsync(sub.topic, {\n qos: sub.options.qos,\n rh: sub.options.rh,\n rap: sub.options.rap,\n nl: sub.options.nl,\n properties: {\n subscriptionIdentifier: group.id,\n },\n })\n }\n\n return sub\n }\n\n async subscribeStringAsync(\n topic: string,\n options?: Partial<SubscriptionOptions>,\n ): Promise<Subscription<string>> {\n return this.subscribeAsync(topic, stringParser, options)\n }\n\n async subscribeJsonAsync<T>(\n topic: string,\n options?: Partial<SubscriptionOptions>,\n ): Promise<Subscription<T>> {\n return this.subscribeAsync<T>(topic, jsonParser, options)\n }\n\n async subscribeBinaryAsync(\n topic: string,\n options?: Partial<SubscriptionOptions>,\n ): Promise<Subscription<Buffer>> {\n return this.subscribeAsync(topic, binaryParser, options)\n }\n\n static async connectAsync(...args: ConnectArgs): Promise<BetterMQTT> {\n const client = await mqtt.connectAsync(...(args as [any, any]))\n return new BetterMQTT(client)\n }\n\n static connect(...args: ConnectArgs): BetterMQTT {\n const client = mqtt.connect(...(args as [any, any]))\n return new BetterMQTT(client)\n }\n\n end(endClient = true) {\n const subs = this.subscriptions.all()\n for (const sub of subs) {\n sub.emit('end')\n if (endClient) {\n this.unsubscribe(sub)\n }\n }\n\n if (endClient) {\n this.client.end()\n }\n\n this.emit('end')\n }\n\n async endAsync(endClient = true) {\n const subs = this.subscriptions.all()\n for (const sub of subs) {\n sub.emit('end')\n }\n\n if (endClient) {\n await Promise.all(subs.map((sub) => this.unsubscribeAsync(sub)))\n await this.client.endAsync()\n }\n\n this.emit('end')\n }\n}\n","// lib.ts\n\n/**\n * Matches an MQTT topic against a subscription pattern and extracts the wildcard parameters.\n *\n * @param topic The topic string to test (e.g., \"system/events/ev123\").\n * @param pattern The subscription pattern (e.g., \"system/events/+\").\n * @returns An array of the captured parameter strings, or `null` if the topic does not match or the pattern is invalid.\n */\nexport function matchTopic(\n topic: string,\n pattern: string,\n): { params: string[] } | null {\n if (!topic || !pattern) {\n return null\n }\n\n const topicSegments = topic.split('/')\n const patternSegments = pattern.split('/')\n\n // Handle MQTT shared subscriptions\n if (patternSegments[0] === '$share') {\n if (patternSegments.length < 3) {\n return null // Invalid $share pattern\n }\n patternSegments.splice(0, 2) // Remove $share and group-name\n } else if (patternSegments[0] === '$queue') {\n if (patternSegments.length < 2) {\n return null // Invalid $queue pattern\n }\n patternSegments.shift() // Remove $queue\n }\n\n const params: string[] = []\n const patternLen = patternSegments.length\n const topicLen = topicSegments.length\n\n for (let i = 0; i < patternLen; i++) {\n const patternSegment = patternSegments[i]\n\n if (patternSegment === '#') {\n // # must be the last segment\n if (i !== patternLen - 1) {\n return null\n }\n // Capture the rest of the topic\n params.push(topicSegments.slice(i).join('/'))\n return { params }\n }\n\n // If we ran out of topic segments but pattern still has more (and not #), no match\n if (i >= topicLen) {\n return null\n }\n\n const topicSegment = topicSegments[i]\n\n if (patternSegment === '+') {\n params.push(topicSegment)\n } else if (patternSegment !== topicSegment) {\n return null\n }\n }\n\n // If pattern finished but topic has more segments, no match (unless handled by # above)\n if (topicLen > patternLen) {\n return null\n }\n\n return { params }\n}\n","import type { IPublishPacket } from 'mqtt'\nimport { matchTopic } from './match'\nimport type { Subscription } from './subscription'\nimport type { BetterMQTTMessage, SubscriptionOptions } from './types'\n\n/**\n * This is a group of virtual subscriptions (`Subscription` class).\n * Multiple subscriptions can be grouped together if they have the same topic.\n *\n * There is a single SubscriptionGroup per topic.\n * This is due to the fact that MQTT protocol does not allow for\n * multiple subscriptions with the same topic, even if they have different options.\n */\nclass SubscriptionGroup {\n topic: string\n id: number\n subs: Set<Subscription<unknown>>\n options: SubscriptionOptions\n\n retainedMessage: BetterMQTTMessage<Buffer<ArrayBufferLike>> | null = null\n\n constructor(topic: string, id: number, options: SubscriptionOptions) {\n this.topic = topic\n this.id = id\n this.subs = new Set()\n this.options = options\n }\n\n handleMessage(\n topic: string,\n message: Buffer<ArrayBufferLike>,\n _packet: IPublishPacket,\n params?: string[],\n ) {\n const match = params ? { params } : matchTopic(topic, this.topic)\n\n if (!match) {\n return\n }\n\n if (this.options.rh < 2) {\n this.retainedMessage = {\n topic,\n content: message,\n params: match.params,\n }\n }\n\n for (const sub of this.subs) {\n sub.handleMessage(message, topic, match.params)\n }\n }\n\n add(sub: Subscription<unknown>): boolean {\n this.subs.add(sub)\n\n // If we have a retained message, we need to send it to the new subscription\n if (this.retainedMessage) {\n sub.handleMessage(\n this.retainedMessage.content,\n this.retainedMessage.topic,\n this.retainedMessage.params,\n )\n }\n\n if (sub.options.qos !== this.options.qos) {\n return true\n }\n\n if (sub.options.rh !== this.options.rh) {\n return true\n }\n\n if (sub.options.rap !== this.options.rap) {\n return true\n }\n\n if (sub.options.nl !== this.options.nl) {\n return true\n }\n\n return false\n }\n\n remove(sub: Subscription<unknown>) {\n this.subs.delete(sub)\n }\n\n isEmpty() {\n return this.subs.size === 0\n }\n}\n\ntype SubscriptionAddResult = {\n group: SubscriptionGroup\n resubscribe: boolean\n}\n\nexport class SubscriptionManager {\n private nextSubIdentifier = 0\n\n /**\n * Subscription groups by subscription identifier\n */\n private subsById = new Map<number, SubscriptionGroup>()\n\n /**\n * Subscription groups by topic\n */\n private subsByTopic = new Map<string, SubscriptionGroup>()\n\n nextId() {\n return ++this.nextSubIdentifier\n }\n\n add(sub: Subscription<unknown>): SubscriptionAddResult {\n const entry = this.subsByTopic.get(sub.topic)\n // Existing group found\n if (entry) {\n // Add subscription to group\n return {\n resubscribe: entry.add(sub),\n group: entry,\n }\n }\n\n const id = this.nextId()\n const group = new SubscriptionGroup(sub.topic, id, sub.options)\n this.subsById.set(id, group)\n this.subsByTopic.set(sub.topic, group)\n group.add(sub)\n return {\n resubscribe: true,\n group,\n }\n }\n\n remove(sub: Subscription<unknown>) {\n const group = this.subsByTopic.get(sub.topic)\n\n // Subscription not registered\n if (!group) {\n return null\n }\n\n // Remove subscription from group\n group.remove(sub)\n\n // If group is empty, remove it\n if (group.isEmpty()) {\n this.subsById.delete(group.id)\n this.subsByTopic.delete(group.topic)\n return group\n }\n\n return group\n }\n\n handleMessage(\n topic: string,\n message: Buffer<ArrayBufferLike>,\n packet: IPublishPacket,\n ) {\n const subId = packet.properties?.subscriptionIdentifier\n if (!subId) {\n // Fallback if no subscription identifier is present\n for (const [subTopic, group] of this.subsByTopic.entries()) {\n const match = matchTopic(topic, subTopic)\n if (!match) {\n continue\n }\n\n group.handleMessage(topic, message, packet)\n }\n\n return\n }\n\n const subsIds = Array.isArray(subId) ? subId : [subId]\n for (const id of subsIds) {\n const group = this.subsById.get(id)\n if (!group) {\n continue\n }\n\n group.handleMessage(topic, message, packet)\n }\n }\n\n all() {\n const subs: Subscription<unknown>[] = []\n for (const group of this.subsById.values()) {\n for (const sub of group.subs) {\n subs.push(sub)\n }\n }\n\n return subs\n }\n}\n","import { EventEmitter } from 'ee-ts'\nimport type { BetterMQTT } from '.'\nimport { createAsyncGenerator } from './generator'\nimport type { BetterMQTTMessage, SubscriptionOptions } from './types'\n\nexport interface SubscriptionEvents<T> {\n message(message: BetterMQTTMessage<T>): void\n end(): void\n error(error: Error): void\n}\n\nexport class Subscription<T = string> extends EventEmitter<\n SubscriptionEvents<T>\n> {\n private mqtt: BetterMQTT\n\n private generator: AsyncGenerator<BetterMQTTMessage<T>>\n\n topic: string\n\n /** Subscription options */\n options: SubscriptionOptions\n\n parser: (message: Buffer) => T\n\n constructor(opts: {\n mqtt: BetterMQTT\n topic: string\n parser: (message: Buffer) => T\n options?: Partial<SubscriptionOptions>\n }) {\n super()\n\n this.mqtt = opts.mqtt\n this.topic = opts.topic\n this.options = {\n qos: opts.options?.qos ?? 2,\n rh: opts.options?.rh ?? 2,\n rap: opts.options?.rap ?? false,\n nl: opts.options?.nl ?? false,\n }\n this.parser = opts.parser\n\n const { generator, push, end, throwError } =\n createAsyncGenerator<BetterMQTTMessage<T>>()\n\n this.on('message', (message) => {\n push(message)\n })\n\n this.on('end', () => {\n end()\n })\n\n this.on('error', (error) => {\n throwError(error)\n })\n\n this.generator = generator\n }\n\n handleMessage(\n message: Buffer<ArrayBufferLike>,\n topic: string,\n params: string[],\n ) {\n const parsedMessage = this.parser(message)\n this.emit('message', { topic, content: parsedMessage, params })\n }\n\n // The method that makes the class async iterable\n [Symbol.asyncIterator](): AsyncGenerator<BetterMQTTMessage<T>> {\n return this.generator\n }\n\n end() {\n this.mqtt.unsubscribe(this)\n }\n}\n","export interface AsyncGeneratorWithPush<T> {\n push: (value: T) => void\n throwError: (error: Error) => void\n end: () => void\n generator: AsyncGenerator<T>\n}\n\ntype QueueItem<T> =\n | { type: 'value'; value: T }\n | { type: 'error'; error: Error }\n | { type: 'done' }\n\nexport function createAsyncGenerator<T>(): AsyncGeneratorWithPush<T> {\n let resolve: () => void = () => undefined\n // 'reject' is removed as it's not used\n let promise: Promise<void> = new Promise((res) => {\n resolve = res\n // No 'rej' needed as errors are handled via the queue\n })\n\n const queue: QueueItem<T>[] = []\n let closed = false\n\n const push = (value: T): void => {\n if (closed) {\n // console.warn('Attempted to push to a closed generator.')\n return\n }\n queue.push({ type: 'value', value })\n resolve()\n // Create a new promise for the next signal\n promise = new Promise((res) => {\n resolve = res\n })\n }\n\n const throwError = (error: Error): void => {\n if (closed) {\n // console.warn('Attempted to throw error to a closed generator.')\n return\n }\n queue.push({ type: 'error', error })\n resolve()\n // Create a new promise for the next signal\n promise = new Promise((res) => {\n resolve = res\n })\n }\n\n const end = (): void => {\n if (closed) {\n // console.warn('Attempted to end a closed generator.')\n return\n }\n closed = true\n queue.push({ type: 'done' })\n resolve()\n }\n\n async function* generator(): AsyncGenerator<T> {\n while (true) {\n if (queue.length > 0) {\n const item = queue.shift() as QueueItem<T>\n\n if (item.type === 'value') {\n yield item.value\n } else if (item.type === 'error') {\n closed = true\n throw item.error\n } else if (item.type === 'done') {\n break\n }\n } else {\n await promise // Wait for a new value or a signal\n }\n }\n\n closed = true\n }\n\n return { push, throwError, end, generator: generator() }\n}\n"],"mappings":"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","names":["import_ee_ts","mqtt"]}