@@ -6,24 +6,20 @@ const {EventEmitter2} = require('eventemitter2');
66
77const eventify = topic => topic . replace ( / # / g, '**' ) . replace ( / \+ / g, '*' ) ;
88
9+ const asyncMethodNames = [ 'publish' , 'subscribe' , 'unsubscribe' , 'end' ] ;
10+
911/**
1012 * Monkeypatches a `MqttClient` instance.
1113 * Promisifies `end`, `subscribe`, `publish`, and `unsubscribe`.
1214 * Adds special behavior around `on`, `once`, `removeListener`, `emit`, etc.
1315 * @param {MqttClient } client - MqttClient (does not mutate)
14- * @param {Object } connack - Connection acknowledgment object
15- * @param {boolean } connack.sessionPresent - If true, not clean session
1616 * @returns {MqttClient } Patched client
1717 */
18- const toadpatch = ( client , connack ) => {
19- const end = pify ( client . end ) ;
20- const subscribe = pify ( client . subscribe ) ;
21- const publish = pify ( client . publish ) ;
22- const unsubscribe = pify ( client . unsubscribe ) ;
23-
24- Object . defineProperty ( client , 'sessionPresent' , {
25- value : Boolean ( connack . sessionPresent )
26- } ) ;
18+ const toadpatch = client => {
19+ const asyncMethods = asyncMethodNames . reduce (
20+ ( acc , name ) => Object . assign ( acc , { [ name ] : pify ( client [ name ] ) } ) ,
21+ { }
22+ ) ;
2723
2824 /**
2925 * Adapter between MQTT topics (supporting wildcards) and the client events.
@@ -40,35 +36,33 @@ const toadpatch = (client, connack) => {
4036 * @public
4137 * @function
4238 * @param {string } topic - MQTT topic
43- * @param {Buffer|string } message - MQTT messqage
44- * @param { Function } listener - Listener function; called with `message` and raw `packet`
39+ * @param {Function } listener - Listener function; called with `message` and
40+ * raw `packet`
4541 * @param {Object } [opts] - Any options for MQTT subscription
4642 * @param {number } [opts.qos=0] - QoS
4743 * @returns Promise<{{topic, qos}}> Object w/ topic subscribed to and QoS
4844 * granted by broker
4945 */
50- client . subscribe = new Proxy ( subscribe , {
51- async apply ( target , client , [ topic , listener , opts = { } ] ) {
52- if ( typeof topic !== 'string' || typeof listener !== 'function' ) {
53- throw new TypeError ( 'Invalid parameters' ) ;
54- }
46+ client . subscribe = async function toadSubscribe ( topic , listener , opts = { } ) {
47+ if ( typeof topic !== 'string' || typeof listener !== 'function' ) {
48+ throw new TypeError ( 'Invalid parameters' ) ;
49+ }
5550
56- const { toad} = client ;
57- const event = eventify ( topic ) ;
58- toad . on ( event , listener ) ;
51+ const { toad} = this ;
52+ const event = eventify ( topic ) ;
53+ toad . on ( event , listener ) ;
5954
60- // TODO: find a way to not subscribe to already-subscribed topics
61- // TODO: note that a different QoS requires a new subscription
62- // TODO: even if the topic is identical!
63- try {
64- const result = await target . apply ( client , [ topic , opts ] ) ;
65- return result . shift ( ) ;
66- } catch ( err ) {
67- toad . removeListener ( event , listener ) ;
68- throw err ;
69- }
55+ // TODO: find a way to not subscribe to already-subscribed topics
56+ // TODO: note that a different QoS requires a new subscription
57+ // TODO: even if the topic is identical!
58+ try {
59+ const result = await asyncMethods . subscribe . call ( this , topic , opts ) ;
60+ return result . shift ( ) ;
61+ } catch ( err ) {
62+ toad . removeListener ( event , listener ) ;
63+ throw err ;
7064 }
71- } ) ;
65+ } ;
7266
7367 /**
7468 * Topic must match exactly.
@@ -80,48 +74,42 @@ const toadpatch = (client, connack) => {
8074 * @param {Function } listener - Listener function to remove
8175 * @returns {Promise<void> }
8276 */
83- client . unsubscribe = new Proxy ( unsubscribe , {
84- async apply ( target , client , [ topic , listener ] ) {
85- const { toad} = client ;
86- const event = eventify ( topic ) ;
87- toad . removeListener ( event , listener ) ;
88- if ( ! toad . listenerCount ( event ) ) {
89- return target . apply ( client , topic ) ;
90- }
77+ client . unsubscribe = async function toadUnsubscribe ( topic , listener ) {
78+ const { toad} = this ;
79+ const event = eventify ( topic ) ;
80+ toad . removeListener ( event , listener ) ;
81+ if ( ! toad . listenerCount ( event ) ) {
82+ return asyncMethods . unsubscribe . call ( this , topic ) ;
9183 }
92- } ) ;
84+ } ;
9385
9486 /**
9587 * Disconnects client (if connected)
9688 * @function
9789 * @public
9890 * @returns {Promise<void> }
9991 */
100- client . end = new Proxy ( end , {
101- async apply ( target , client , ...args ) {
102- if ( client . connected ) {
103- return target . apply ( client , ...args ) ;
104- }
92+ client . end = async function toadEnd ( force ) {
93+ if ( this . connected ) {
94+ await asyncMethods . end . call ( this , force ) ;
95+ this . disconnecting = false ;
10596 }
106- } ) ;
97+ } ;
10798
10899 /**
109100 * Publishes a message to a topic
110101 * @function
102+ * @public
111103 * @returns {Promise<void> }
112104 */
113- client . publish = new Proxy ( publish , {
114- async apply ( target , client , ...args ) {
115- return target . apply ( client , ...args ) ;
116- }
117- } ) ;
105+ client . publish = asyncMethods . publish ;
118106
119107 /**
120108 * On any received message, delegate to the internal EE2 instance
121109 * where the real listeners for subscriptions are stored.
122110 */
123- client . on ( 'message' , ( topic , message , packet ) => {
124- client . toad . emit ( eventify ( topic ) , message , packet ) ;
111+ client . on ( 'message' , function ( topic , message , packet ) {
112+ this . toad . emit ( eventify ( topic ) , message , packet ) ;
125113 } ) ;
126114
127115 return client ;
@@ -135,11 +123,20 @@ const toadpatch = (client, connack) => {
135123 * @returns {Promise<MqttClient> } Patched `MqttClient` instance
136124 */
137125exports . connect = ( ...args ) => {
138- const client = MQTT . connect ( ...args ) ;
139126 return new Promise ( ( resolve , reject ) => {
140- client . on ( 'error' , reject ) . on ( 'connect' , connack => {
141- resolve ( toadpatch ( client , connack ) ) ;
142- } ) ;
127+ MQTT . connect ( ...args )
128+ . on ( 'connect' , function ( connack ) {
129+ /**
130+ * If `false`, this is a clean session
131+ * @public
132+ * @memberOf client
133+ */
134+ this . sessionPresent = Boolean ( connack . sessionPresent ) ;
135+ } )
136+ . once ( 'error' , reject )
137+ . once ( 'connect' , function ( ) {
138+ resolve ( toadpatch ( this ) ) ;
139+ } ) ;
143140 } ) ;
144141} ;
145142
0 commit comments