UNPKG

amplify-appsync-simulator

Version:

An AppSync Simulator to test AppSync API.

203 lines 6.75 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MQTTServer = void 0; const mqtt_connection_1 = __importDefault(require("mqtt-connection")); const ws_1 = __importDefault(require("ws")); const steed_1 = __importDefault(require("steed")); const pino_1 = __importDefault(require("pino")); const lodash_1 = require("lodash"); const nanoid_1 = require("nanoid"); const trie_listener_1 = require("./trie-listener"); const client_1 = require("./client"); const events_1 = require("events"); const DEFAULT_OPTIONS = { maxConnections: 10000000, backend: { wildcardOne: '+', wildcardSome: '#', }, stats: false, publishNewClient: true, publishClientDisconnect: true, publishSubscriptions: true, maxInflightMessages: 1024, onQoS2publish: 'noack', logger: { name: 'amplify-mqtt-server', level: 'warn', }, }; const nop = () => { }; class MQTTServer extends events_1.EventEmitter { constructor(options = {}, callback = (err, data) => { }) { super(); this.callback = callback; this.options = (0, lodash_1.defaultsDeep)(options, DEFAULT_OPTIONS); this._dedupId = 0; this.clients = {}; this.closed = false; this.closed = false; this.logger = (0, pino_1.default)(this.options.logger); this.onQoS2publish = this.options.onQoS2publish; this.id = this.options.id || (0, nanoid_1.nanoid)(7); new Promise(resolve => { const listener = new trie_listener_1.TrieListener(this.options.backend); listener.once('ready', function () { resolve(listener); }); }) .then(listener => { this.listener = listener; this.init(); }) .catch(err => { callback(err); }); } init() { this.on('clientConnected', client => { if (this.options.publishNewClient) { this.publish({ topic: `$SYS/${this.id}/new/clients`, payload: client.id, }); } this.clients[client.id] = client; }); this.once('ready', () => { this.callback(null, this); }); this.on('ready', () => { this.listener.subscribe('$SYS/+/new/clients', (topic, payload) => { const serverId = topic.split('/')[1]; const clientId = payload; if (this.clients[clientId] && serverId !== this.id) { this.clients[clientId].close(null, 'new connection request'); } }); }); if (this.options.publishSubscriptions) { this.on('subscribed', (topic, client) => { this.publish({ topic: `$SYS/${this.id}/new/subscribes`, payload: JSON.stringify({ clientId: client.id, topic: topic, }), }); }); this.on('unsubscribed', (topic, client) => { this.publish({ topic: '$SYS/' + this.id + '/new/unsubscribes', payload: JSON.stringify({ clientId: client.id, topic: topic, }), }); }); } this.on('clientDisconnected', client => { if (this.options.publishClientDisconnect) { this.publish({ topic: '$SYS/' + this.id + '/disconnect/clients', payload: client.id, }); } delete this.clients[client.id]; }); } toString() { return 'AmplifyMQTTServer.Server'; } subscribe(topic, callback, done) { this.listener.subscribe(topic, callback, done); } publish(packet, client, callback) { let logger = this.logger; if (typeof client === 'function') { callback = client; client = null; } else if (client) { logger = client.logger; } if (!callback) { callback = nop; } const newPacket = { topic: packet.topic, payload: packet.payload, messageId: (0, nanoid_1.nanoid)(7), qos: packet.qos, retain: packet.retain, }; const opts = { qos: packet.qos, messageId: newPacket.messageId, }; if (client) { opts.clientId = client.id; } if (this.closed) { logger.debug({ packet: newPacket }, 'not delivering because we are closed'); return; } this.listener.publish(newPacket.topic, newPacket.payload, opts, () => { if (newPacket.topic.indexOf('$SYS') >= 0) { logger.trace({ packet: newPacket }, 'published packet'); } else { logger.debug({ packet: newPacket }, 'published packet'); } this.emit('published', newPacket, client); callback(undefined, newPacket); }); } close(callback = nop) { const stuffToClose = []; if (this.closed) { return callback(); } this.closed = true; Object.keys(this.clients).forEach(i => { stuffToClose.push(this.clients[i]); }); steed_1.default.each(stuffToClose, (toClose, cb) => { try { toClose.close(cb, 'server closed'); } catch (e) { } }, () => { this.listener.close(() => { this.logger.info('server closed'); this.emit('closed'); callback(); }); }); } updateOfflinePacket(client, originMessageId, packet, callback) { if (callback) { callback(null, packet); } } attachHttpServer(server, path) { const opt = { server: server }; if (path) { opt.path = path; } const wss = new ws_1.default.Server(opt); wss.on('connection', socket => { const stream = ws_1.default.createWebSocketStream(socket, {}); const conn = new mqtt_connection_1.default(stream); new client_1.Client(conn, this); }); } nextDedupId() { return this._dedupId++; } } exports.MQTTServer = MQTTServer; //# sourceMappingURL=server.js.map