UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

119 lines 4.29 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const async_mqtt_1 = __importDefault(require("async-mqtt")); const merge_1 = __importDefault(require("lodash/merge")); const get_1 = __importDefault(require("lodash/get")); const unset_1 = __importDefault(require("lodash/unset")); const omit_1 = __importDefault(require("lodash/omit")); const broker_1 = __importDefault(require("./broker")); class MQTTClient extends broker_1.default { constructor() { super(...arguments); this._client = null; } get client() { if (this._client === null) { throw MQTTClient.ERRORS.NOT_CONNECTED; } return this._client; } async connect() { if (this._client !== null) { return this; } this._client = await async_mqtt_1.default.connectAsync(this.config.url, (0, merge_1.default)({}, this.config.options, { protocolVersion: 5, clean: true, })); this._client.on('message', this.onMessage.bind(this)); return this; } async end() { if (this._client === null) { return; } await this._client.end(); this._client = null; return this; } authenticate(tokens, handler) { return (event, route, headers, opts) => { const token = headers?.['authorization']; if (tokens.find((t) => t.token === token)) { return handler(event, route, headers, opts); } this.telemetry?.logger.debug('[events#authenticate] Authentication failed', { event, }); }; } onMessage(topic, message, packet) { const route = this.getRoute(topic); if (route === null) { return; } const event = JSON.parse(message.toString()); const headers = packet?.properties?.userProperties || {}; this.telemetry?.logger.debug('[services#mqtt] Handling event', { topic, event, headers: (0, omit_1.default)(headers, 'authorization'), }); const isValid = route.validate(event); if (!isValid) { this.logOnInvalid(event, route); return; } /* istanbul ignore next */ const ack = async () => null; /* istanbul ignore next */ const nack = async () => null; this.emit(route.original, event, this.parseTopic(topic, route), headers, { source: 'mqtt', original: packet, delivery: 0, ack, nack, }); } publish(topic, payload, options = {}) { let _options = (0, merge_1.default)({}, { properties: { userProperties: (0, get_1.default)(this.config, 'options.properties.userProperties', {}), }, }, options); if (Object.keys((0, get_1.default)(_options, 'properties.userProperties', {})).length === 0) { _options = (0, unset_1.default)(_options, 'properies.userProperties'); } return this.client.publish(this.topicWithNamespace(topic), JSON.stringify(payload), _options); } subscribe(topic, schema) { const mappedTopic = this.mapTopic(topic, schema); this.topics.set(mappedTopic.topic, mappedTopic); this.addChannelToSpec(topic, schema); return this.client.subscribe(`$share/${this.config.group}/${mappedTopic.topic}`); } async next(topic, timeout = 1000) { let resolve; let _timeout; const promise = new Promise((_resolve, _reject) => { resolve = _resolve; _timeout = setTimeout(() => _reject(new Error('[mqtt#next] Message timeout')), timeout); }); const handler = (event) => { clearTimeout(_timeout); resolve(event); this.removeListener(topic, handler); }; this.on(topic, handler); return promise; } } MQTTClient.ERRORS = { NOT_CONNECTED: new Error('MQTT not connected yet'), }; exports.default = MQTTClient; //# sourceMappingURL=mqtt.js.map