From d707e3761eac6d739c093f189146aea951b7e65f Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Thu, 1 Oct 2020 14:22:49 -0400 Subject: [PATCH 1/9] Adds base mqtt.ts and mqtt.test.ts transports --- package-lock.json | 550 +++++++++++++++++++++++++++++++++--- package.json | 1 + src/transports/mqtt.test.ts | 33 +++ src/transports/mqtt.ts | 36 +++ 4 files changed, 587 insertions(+), 33 deletions(-) create mode 100644 src/transports/mqtt.test.ts create mode 100644 src/transports/mqtt.ts diff --git a/package-lock.json b/package-lock.json index 223ee8ab..f8e949c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1315,6 +1315,14 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "async-mqtt": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async-mqtt/-/async-mqtt-2.6.1.tgz", + "integrity": "sha512-EkXAwRzwMaPC6ji0EvNeM5OMe6VjMhEKVJJUN7gu/hGzkcDpZtaI34nUwdwCMbjQB3pnuSOHqQMFKsUpg+D8kA==", + "requires": { + "mqtt": "^4.1.0" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1432,8 +1440,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base": { "version": "0.11.2", @@ -1490,6 +1497,11 @@ } } }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -1499,6 +1511,33 @@ "tweetnacl": "^0.14.3" } }, + "bl": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -1530,7 +1569,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1569,11 +1607,19 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "bytes": { "version": "3.1.0", @@ -1602,6 +1648,15 @@ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" }, + "callback-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/callback-stream/-/callback-stream-1.1.0.tgz", + "integrity": "sha1-RwGlEmbwbgbqpx/BcjOCLYdfSQg=", + "requires": { + "inherits": "^2.0.1", + "readable-stream": "> 1.0.0 < 3.0.0" + } + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1737,6 +1792,22 @@ "delayed-stream": "~1.0.0" } }, + "commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "requires": { + "leven": "^2.1.0", + "minimist": "^1.1.0" + }, + "dependencies": { + "leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" + } + } + }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -1746,8 +1817,18 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } }, "connect": { "version": "3.7.0", @@ -1783,8 +1864,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cors": { "version": "2.8.5", @@ -1831,6 +1911,15 @@ } } }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1980,6 +2069,17 @@ "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==" }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, "easy-stack": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz", @@ -2029,7 +2129,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -2043,6 +2142,71 @@ "is-arrayish": "^0.2.1" } }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2084,6 +2248,15 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "event-pubsub": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", @@ -2180,11 +2353,25 @@ } } }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz", + "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==" + } + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "extend-shallow": { "version": "3.0.2", @@ -2387,8 +2574,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.1.3", @@ -2449,7 +2635,6 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2459,6 +2644,32 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2560,6 +2771,17 @@ } } }, + "help-me": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-1.1.0.tgz", + "integrity": "sha1-jy1QjQYAtKRW2i8IZVbn5cBWo8Y=", + "requires": { + "callback-stream": "^1.0.2", + "glob-stream": "^6.1.0", + "through2": "^2.0.1", + "xtend": "^4.0.0" + } + }, "hosted-git-info": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", @@ -2618,6 +2840,11 @@ "safer-buffer": ">= 2.1.2 < 3.0.0" } }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "import-local": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", @@ -2638,7 +2865,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -2655,6 +2881,15 @@ "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", "dev": true }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, "is-accessor-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", @@ -2757,6 +2992,11 @@ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -2769,6 +3009,19 @@ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", "dev": true }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2790,6 +3043,14 @@ "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=", "dev": true }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -2801,6 +3062,14 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, "is-url": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", @@ -2809,8 +3078,7 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "is-wsl": { "version": "2.2.0", @@ -2825,8 +3093,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -4174,6 +4441,11 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -4366,7 +4638,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4374,8 +4645,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "mixin-deep": { "version": "1.3.2", @@ -4404,6 +4674,69 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "mqtt": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.2.1.tgz", + "integrity": "sha512-Iv893r+jWlo5GkNcPOfCGwW8M49IixwHiKLFFYTociEymSibUVCORVEjPXWPGzSxhn7BdlUeHicbRmWiv0Crkg==", + "requires": { + "base64-js": "^1.3.0", + "commist": "^1.0.0", + "concat-stream": "^1.6.2", + "debug": "^4.1.1", + "end-of-stream": "^1.4.1", + "es6-map": "^0.1.5", + "help-me": "^1.0.1", + "inherits": "^2.0.3", + "minimist": "^1.2.5", + "mqtt-packet": "^6.3.2", + "pump": "^3.0.0", + "readable-stream": "^2.3.6", + "reinterval": "^1.1.0", + "split2": "^3.1.0", + "ws": "^7.3.1", + "xtend": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "mqtt-packet": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.6.0.tgz", + "integrity": "sha512-LvghnKMFC70hKWMVykmhJarlO5e7lT3t9s9A2qPCUx+lazL3Mq55U+eCV0eLi7/nRRQYvEUWo/2tTo89EjnCJQ==", + "requires": { + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -4434,6 +4767,11 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -4607,7 +4945,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -4643,6 +4980,14 @@ "word-wrap": "~1.2.3" } }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", + "requires": { + "readable-stream": "^2.0.1" + } + }, "p-each-series": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", @@ -4708,6 +5053,11 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4717,8 +5067,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { "version": "2.0.1", @@ -4786,6 +5135,11 @@ "react-is": "^16.12.0" } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "prompts": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz", @@ -4806,12 +5160,32 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -4889,6 +5263,20 @@ "type-fest": "^0.8.1" } }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -4899,11 +5287,15 @@ "safe-regex": "^1.1.0" } }, + "reinterval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", + "integrity": "sha1-M2Hs+jymwYKDOA3Qu5VG85D17Oc=" + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, "repeat-element": { "version": "1.1.3", @@ -5078,8 +5470,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safe-regex": { "version": "1.1.0", @@ -5522,6 +5913,26 @@ "extend-shallow": "^3.0.0" } }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -5593,6 +6004,11 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==" + }, "string-length": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz", @@ -5614,6 +6030,14 @@ "strip-ansi": "^6.0.0" } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -5693,12 +6117,39 @@ "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", "dev": true }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, "tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", "dev": true }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -5820,6 +6271,11 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -5850,6 +6306,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -5865,6 +6326,11 @@ "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==", "dev": true }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, "union-value": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", @@ -5877,6 +6343,15 @@ "set-value": "^2.0.1" } }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, "universalify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", @@ -5947,6 +6422,11 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -6114,8 +6594,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write-file-atomic": { "version": "3.0.3", @@ -6146,6 +6625,11 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index 08600517..7ecaeeda 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "license": "Apache-2.0", "dependencies": { "@open-rpc/schema-utils-js": "^1.14.0", + "async-mqtt": "^2.6.1", "body-parser": "^1.19.0", "connect": "^3.7.0", "cors": "^2.8.5", diff --git a/src/transports/mqtt.test.ts b/src/transports/mqtt.test.ts new file mode 100644 index 00000000..dc6ee793 --- /dev/null +++ b/src/transports/mqtt.test.ts @@ -0,0 +1,33 @@ +import examples from "@open-rpc/examples"; +import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js"; +import { Router } from "../router"; +import MQTTTransport from "./mqtt"; + +// import fetch from "node-fetch"; +import { JSONRPCResponse } from "./server-transport"; + +describe('mqtt transport', () => { + let transport: MQTTTransport; + beforeAll(async () => { + const simpleMathExample = await parseOpenRPCDocument(examples.simpleMath); + transport = new MQTTTransport({ + broker: "tcp://localhost:1883", + inTopic: "inTopic", + outTopic: "outTopic" + }); + + const router = new Router(simpleMathExample, { mockMode: true }); + + transport.addRouter(router); + + await transport.connect(); + }); + + afterAll(() => { + transport.end(); + }) + + it("can connect to the broker", () => { + expect(transport.client.connected).toBeTruthy() + }) +}); diff --git a/src/transports/mqtt.ts b/src/transports/mqtt.ts new file mode 100644 index 00000000..cea50d9b --- /dev/null +++ b/src/transports/mqtt.ts @@ -0,0 +1,36 @@ +import cors from "cors"; +import { json as jsonParser } from "body-parser"; +import connect, { HandleFunction } from "connect"; +// import http, { ServerOptions } from "http"; +import AsyncMQTT, { AsyncClient } from "async-mqtt" +import ServerTransport, { JSONRPCRequest } from "./server-transport"; + +export interface MQTTServerTransportOptions { + // middleware: HandleFunction[]; + // server: string; + // port: number; + broker: string; + inTopic: string; + outTopic: string; +} + + +export default class MQTTServerTransport extends ServerTransport { + private options: MQTTServerTransportOptions + public client: any + // public client: AsyncMQTT.AsyncClient + + constructor(options: MQTTServerTransportOptions) { + super() + this.options = { ...options } + this.client = null + } + + public async connect(): Promise { + this.client = await AsyncMQTT.connectAsync(this.options.broker); + } + + public end(): void { + this.client.end() + } +} From 9a7b8a543d135532cca8067ffe2a47279c97bd0f Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Thu, 1 Oct 2020 16:24:15 -0400 Subject: [PATCH 2/9] Answers JSON-RPC requests --- src/transports/mqtt.test.ts | 35 ++++++++++++++++++++++++++++------- src/transports/mqtt.ts | 18 ++++++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/transports/mqtt.test.ts b/src/transports/mqtt.test.ts index dc6ee793..2e4070ed 100644 --- a/src/transports/mqtt.test.ts +++ b/src/transports/mqtt.test.ts @@ -2,25 +2,29 @@ import examples from "@open-rpc/examples"; import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js"; import { Router } from "../router"; import MQTTTransport from "./mqtt"; - +import AsyncMQTT from "async-mqtt" // import fetch from "node-fetch"; import { JSONRPCResponse } from "./server-transport"; describe('mqtt transport', () => { + const mqttOptions = { + broker: "tcp://localhost:1883", + inTopic: "inTopic", + outTopic: "outTopic" + } let transport: MQTTTransport; + let mqttClient: AsyncMQTT.AsyncClient; beforeAll(async () => { const simpleMathExample = await parseOpenRPCDocument(examples.simpleMath); - transport = new MQTTTransport({ - broker: "tcp://localhost:1883", - inTopic: "inTopic", - outTopic: "outTopic" - }); + transport = new MQTTTransport(mqttOptions); const router = new Router(simpleMathExample, { mockMode: true }); transport.addRouter(router); await transport.connect(); + mqttClient = await AsyncMQTT.connectAsync(mqttOptions.broker) + mqttClient.subscribe(mqttOptions.outTopic) }); afterAll(() => { @@ -28,6 +32,23 @@ describe('mqtt transport', () => { }) it("can connect to the broker", () => { - expect(transport.client.connected).toBeTruthy() + expect(transport.client?.connected).toBeTruthy() + }) + + it("can answer to simple JSON-RPC", (done) => { + const messageHandler = (topic: string, payload: Buffer) => { + const response = JSON.parse(payload.toString()) + expect(response.result).toBe(4); + mqttClient.off('message', messageHandler) + done() + } + mqttClient.on('message', messageHandler) + + mqttClient.publish(mqttOptions.inTopic, JSON.stringify({ + id: "0", + jsonrpc: "2.0", + method: "addition", + params: [2, 2], + })) }) }); diff --git a/src/transports/mqtt.ts b/src/transports/mqtt.ts index cea50d9b..82707f1e 100644 --- a/src/transports/mqtt.ts +++ b/src/transports/mqtt.ts @@ -17,7 +17,7 @@ export interface MQTTServerTransportOptions { export default class MQTTServerTransport extends ServerTransport { private options: MQTTServerTransportOptions - public client: any + public client: AsyncMQTT.AsyncClient | null // public client: AsyncMQTT.AsyncClient constructor(options: MQTTServerTransportOptions) { @@ -28,9 +28,23 @@ export default class MQTTServerTransport extends ServerTransport { public async connect(): Promise { this.client = await AsyncMQTT.connectAsync(this.options.broker); + this.client.subscribe(this.options.inTopic) + this.client.on('message', (topic: string, payload: Buffer) => { + this.mqttRouterHandler(JSON.parse(payload.toString())) + }) } public end(): void { - this.client.end() + this.client?.end() + } + + private async mqttRouterHandler(payload: any): Promise { + let result = null; + if (payload instanceof Array) { + result = await Promise.all(payload.map((r: JSONRPCRequest) => super.routerHandler(r))); + } else { + result = await super.routerHandler(payload); + } + this.client?.publish(this.options.outTopic, JSON.stringify(result)) } } From 91a424f7f97b730418d07dae7cbcef4c12d82852 Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Thu, 1 Oct 2020 16:32:10 -0400 Subject: [PATCH 3/9] Adds MQTT broker in test --- package-lock.json | 191 ++++++++++++++++++++++++++++++++++-- package.json | 1 + src/transports/mqtt.test.ts | 10 +- 3 files changed, 194 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8e949c7..c035817c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1208,6 +1208,73 @@ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, + "aedes": { + "version": "0.42.6", + "resolved": "https://registry.npmjs.org/aedes/-/aedes-0.42.6.tgz", + "integrity": "sha512-x2jfb6zmRNRDHOkcadEhjUE81wsPFippNncrI1IX8YnEt4YrbpEmuSNbKYssqWW0p1c2Q2iaFVS/a3FiFOZ14Q==", + "dev": true, + "requires": { + "aedes-packet": "^2.3.1", + "aedes-persistence": "^8.1.1", + "aedes-protocol-decoder": "^1.0.0", + "bulk-write-stream": "^2.0.1", + "end-of-stream": "^1.4.4", + "fastfall": "^1.5.1", + "fastparallel": "^2.3.0", + "fastseries": "^2.0.0", + "mqemitter": "^4.2.0", + "mqtt-packet": "^6.3.2", + "proxy-protocol-js": "^4.0.4", + "readable-stream": "^3.6.0", + "retimer": "^2.0.0", + "reusify": "^1.0.4", + "shortid": "^2.2.15", + "uuid": "^8.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "aedes-packet": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/aedes-packet/-/aedes-packet-2.3.1.tgz", + "integrity": "sha512-LqBd57uc2rui2RbjycW17dylglejG26mM4ewVXGNDnVp/SUHFVEgm7d1HTmYrnSkSCNoHti042qgcTwv/F+BtQ==", + "dev": true, + "requires": { + "mqtt-packet": "^6.3.0" + } + }, + "aedes-persistence": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/aedes-persistence/-/aedes-persistence-8.1.1.tgz", + "integrity": "sha512-Szvmkmk63LiCYmRDYv74Z/jTdYYstLdl8bWl7yANDlWUyEn3DIvMLJdgIdgfuTppobfFsb9biXAxjDpUWJDMlw==", + "dev": true, + "requires": { + "aedes-packet": "^2.3.1", + "from2": "^2.3.0", + "qlobber": "^5.0.0" + } + }, + "aedes-protocol-decoder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/aedes-protocol-decoder/-/aedes-protocol-decoder-1.0.0.tgz", + "integrity": "sha512-nzWwSetptIFFk0gXtXBvmBPUD6HwuZKeVm/8mRJqEKfBJ4ZnvgpcO5CFwEDzTi884jOWTIBaJAWll3QLYsOCFQ==", + "dev": true, + "requires": { + "forwarded": "^0.1.2", + "proxy-protocol-js": "^4.0.3" + } + }, "ajv": { "version": "6.12.3", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", @@ -1621,6 +1688,29 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, + "bulk-write-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bulk-write-stream/-/bulk-write-stream-2.0.1.tgz", + "integrity": "sha512-XWOLjgHtpDasHfwM8oO4df1JoZwa7/OwTsXDzh4rUTo+9CowzeOFBZz43w+H14h1fyq+xl28tVIBrdjcjj4Gug==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -2481,6 +2571,31 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastfall": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", + "integrity": "sha1-P+4DMxpJ0dObPN96XpzWb0dee5Q=", + "dev": true, + "requires": { + "reusify": "^1.0.0" + } + }, + "fastparallel": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.0.tgz", + "integrity": "sha512-sacwQ7wwKlQXsa7TN24UvMBLZNLmVcPhmxccC9riFqb3N+fSczJL8eWdnZodZ/KijGVgNBBfvF/NeXER08uXnQ==", + "dev": true, + "requires": { + "reusify": "^1.0.4", + "xtend": "^4.0.2" + } + }, + "fastseries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-2.0.0.tgz", + "integrity": "sha512-XBU9RXeoYc2/VnvMhplAxEmZLfIk7cvTBu+xwoBuTI8pL19E03cmca17QQycKIdxgwCeFA/a4u27gv1h3ya5LQ==", + "dev": true + }, "fb-watchman": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", @@ -2551,6 +2666,12 @@ "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==" }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -2560,6 +2681,16 @@ "map-cache": "^0.2.2" } }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, "fs-extra": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", @@ -4674,6 +4805,16 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "mqemitter": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/mqemitter/-/mqemitter-4.4.0.tgz", + "integrity": "sha512-XWoue2+i4wLWxtPCRdZk3bNJc2+FhomyA3QzxBM4+4Iui/+iGLeubeShtKa8MwZ0HXVLJqWTMznkCsYs7xjiQQ==", + "dev": true, + "requires": { + "fastparallel": "^2.3.0", + "qlobber": "^5.0.0" + } + }, "mqtt": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/mqtt/-/mqtt-4.2.1.tgz", @@ -4742,6 +4883,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==", + "dev": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -5150,6 +5297,12 @@ "sisteransi": "^1.0.4" } }, + "proxy-protocol-js": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/proxy-protocol-js/-/proxy-protocol-js-4.0.5.tgz", + "integrity": "sha512-53BHGoSSquDJg7fyDrMKWa85jfF34LPKAeRSij+Eiktlh2YE4rAk5U9uba3mGRswE/grDiAi2mZWknbzbXiB9w==", + "dev": true + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -5191,6 +5344,12 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, + "qlobber": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/qlobber/-/qlobber-5.0.3.tgz", + "integrity": "sha512-wW4GTZPePyh0RgOsM18oDyOUlXfurVRgoNyJfS+y7VWPyd0GYhQp5T2tycZFZjonH+hngxIfklGJhTP/ghidgQ==", + "dev": true + }, "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", @@ -5452,6 +5611,18 @@ "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" }, + "retimer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/retimer/-/retimer-2.0.0.tgz", + "integrity": "sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -5706,6 +5877,15 @@ "dev": true, "optional": true }, + "shortid": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.15.tgz", + "integrity": "sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw==", + "dev": true, + "requires": { + "nanoid": "^2.1.0" + } + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", @@ -6433,11 +6613,10 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "dev": true, - "optional": true + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", + "dev": true }, "v8-to-istanbul": { "version": "6.0.1", @@ -6666,4 +6845,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 7ecaeeda..c45599f9 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@types/node-fetch": "^2.5.7", "@types/node-ipc": "^9.1.3", "@types/ws": "^7.2.6", + "aedes": "^0.42.6", "jest": "^26.1.0", "lodash": "^4.17.19", "node-fetch": "^2.6.0", diff --git a/src/transports/mqtt.test.ts b/src/transports/mqtt.test.ts index 2e4070ed..87ea6630 100644 --- a/src/transports/mqtt.test.ts +++ b/src/transports/mqtt.test.ts @@ -2,11 +2,14 @@ import examples from "@open-rpc/examples"; import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js"; import { Router } from "../router"; import MQTTTransport from "./mqtt"; -import AsyncMQTT from "async-mqtt" -// import fetch from "node-fetch"; +import AsyncMQTT from "async-mqtt"; +import Aedes from "aedes"; +import Net from "net"; + import { JSONRPCResponse } from "./server-transport"; describe('mqtt transport', () => { + const mqttBroker = Net.createServer(Aedes().handle); const mqttOptions = { broker: "tcp://localhost:1883", inTopic: "inTopic", @@ -15,6 +18,7 @@ describe('mqtt transport', () => { let transport: MQTTTransport; let mqttClient: AsyncMQTT.AsyncClient; beforeAll(async () => { + const simpleMathExample = await parseOpenRPCDocument(examples.simpleMath); transport = new MQTTTransport(mqttOptions); @@ -22,6 +26,7 @@ describe('mqtt transport', () => { transport.addRouter(router); + mqttBroker.listen(1883) await transport.connect(); mqttClient = await AsyncMQTT.connectAsync(mqttOptions.broker) mqttClient.subscribe(mqttOptions.outTopic) @@ -29,6 +34,7 @@ describe('mqtt transport', () => { afterAll(() => { transport.end(); + mqttBroker.close(); }) it("can connect to the broker", () => { From 6d43a08c80a289b6590f1f25fc95166861900f98 Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Thu, 1 Oct 2020 16:34:08 -0400 Subject: [PATCH 4/9] Removes unused import --- src/transports/mqtt.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/transports/mqtt.test.ts b/src/transports/mqtt.test.ts index 87ea6630..bfd211a5 100644 --- a/src/transports/mqtt.test.ts +++ b/src/transports/mqtt.test.ts @@ -6,8 +6,6 @@ import AsyncMQTT from "async-mqtt"; import Aedes from "aedes"; import Net from "net"; -import { JSONRPCResponse } from "./server-transport"; - describe('mqtt transport', () => { const mqttBroker = Net.createServer(Aedes().handle); const mqttOptions = { From 6ec12b1c8cb19300afcede93c4d14f417998ae92 Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Thu, 1 Oct 2020 16:35:21 -0400 Subject: [PATCH 5/9] Removes commented out code --- src/transports/mqtt.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/transports/mqtt.ts b/src/transports/mqtt.ts index 82707f1e..9cf1470d 100644 --- a/src/transports/mqtt.ts +++ b/src/transports/mqtt.ts @@ -6,9 +6,6 @@ import AsyncMQTT, { AsyncClient } from "async-mqtt" import ServerTransport, { JSONRPCRequest } from "./server-transport"; export interface MQTTServerTransportOptions { - // middleware: HandleFunction[]; - // server: string; - // port: number; broker: string; inTopic: string; outTopic: string; @@ -18,7 +15,6 @@ export interface MQTTServerTransportOptions { export default class MQTTServerTransport extends ServerTransport { private options: MQTTServerTransportOptions public client: AsyncMQTT.AsyncClient | null - // public client: AsyncMQTT.AsyncClient constructor(options: MQTTServerTransportOptions) { super() From e74dff14c8e3e67a91f09a074d7fd5ff302d936e Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Thu, 1 Oct 2020 16:42:27 -0400 Subject: [PATCH 6/9] Adds missing semicolons, removes unused imports --- src/transports/mqtt.test.ts | 12 ++++++------ src/transports/mqtt.ts | 24 ++++++++++-------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/transports/mqtt.test.ts b/src/transports/mqtt.test.ts index bfd211a5..9fc06590 100644 --- a/src/transports/mqtt.test.ts +++ b/src/transports/mqtt.test.ts @@ -24,7 +24,7 @@ describe('mqtt transport', () => { transport.addRouter(router); - mqttBroker.listen(1883) + mqttBroker.listen(1883); await transport.connect(); mqttClient = await AsyncMQTT.connectAsync(mqttOptions.broker) mqttClient.subscribe(mqttOptions.outTopic) @@ -36,17 +36,17 @@ describe('mqtt transport', () => { }) it("can connect to the broker", () => { - expect(transport.client?.connected).toBeTruthy() + expect(transport.client?.connected).toBeTruthy(); }) it("can answer to simple JSON-RPC", (done) => { const messageHandler = (topic: string, payload: Buffer) => { - const response = JSON.parse(payload.toString()) + const response = JSON.parse(payload.toString()); expect(response.result).toBe(4); - mqttClient.off('message', messageHandler) - done() + mqttClient.off('message', messageHandler); + done(); } - mqttClient.on('message', messageHandler) + mqttClient.on('message', messageHandler); mqttClient.publish(mqttOptions.inTopic, JSON.stringify({ id: "0", diff --git a/src/transports/mqtt.ts b/src/transports/mqtt.ts index 9cf1470d..c6d1712a 100644 --- a/src/transports/mqtt.ts +++ b/src/transports/mqtt.ts @@ -1,8 +1,4 @@ -import cors from "cors"; -import { json as jsonParser } from "body-parser"; -import connect, { HandleFunction } from "connect"; -// import http, { ServerOptions } from "http"; -import AsyncMQTT, { AsyncClient } from "async-mqtt" +import AsyncMQTT, { AsyncClient } from "async-mqtt"; import ServerTransport, { JSONRPCRequest } from "./server-transport"; export interface MQTTServerTransportOptions { @@ -13,25 +9,25 @@ export interface MQTTServerTransportOptions { export default class MQTTServerTransport extends ServerTransport { - private options: MQTTServerTransportOptions - public client: AsyncMQTT.AsyncClient | null + private options: MQTTServerTransportOptions; + public client: AsyncMQTT.AsyncClient | null; constructor(options: MQTTServerTransportOptions) { - super() - this.options = { ...options } - this.client = null + super(); + this.options = { ...options }; + this.client = null; } public async connect(): Promise { this.client = await AsyncMQTT.connectAsync(this.options.broker); - this.client.subscribe(this.options.inTopic) + this.client.subscribe(this.options.inTopic); this.client.on('message', (topic: string, payload: Buffer) => { - this.mqttRouterHandler(JSON.parse(payload.toString())) + this.mqttRouterHandler(JSON.parse(payload.toString())); }) } public end(): void { - this.client?.end() + this.client?.end(); } private async mqttRouterHandler(payload: any): Promise { @@ -41,6 +37,6 @@ export default class MQTTServerTransport extends ServerTransport { } else { result = await super.routerHandler(payload); } - this.client?.publish(this.options.outTopic, JSON.stringify(result)) + this.client?.publish(this.options.outTopic, JSON.stringify(result)); } } From aa8fde321836128fe99b63768a4891ec3874ebda Mon Sep 17 00:00:00 2001 From: Erwan d'Orgeville Date: Wed, 7 Oct 2020 14:35:49 -0400 Subject: [PATCH 7/9] Adds MQTTServerTransport to TransportNames type --- src/transports/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transports/index.ts b/src/transports/index.ts index de79e3a3..12211d8a 100644 --- a/src/transports/index.ts +++ b/src/transports/index.ts @@ -3,7 +3,7 @@ import HTTPTransport, { HTTPServerTransportOptions } from "./http"; import HTTPSTransport, { HTTPSServerTransportOptions } from "./https"; import IPCTransport, { IPCServerTransportOptions } from "./ipc"; -export type TransportNames = "IPCTransport" | "HTTPTransport" | "HTTPSTransport" | "WebSocketTransport"; +export type TransportNames = "IPCTransport" | "HTTPTransport" | "HTTPSTransport" | "WebSocketTransport" | "MQTTServerTransport"; export type TransportClasses = WebSocketTransport | HTTPTransport | From f2ef4b1e6179dbdaafaeeceecdb59b63ce9f6fd4 Mon Sep 17 00:00:00 2001 From: Zachary Belford Date: Tue, 3 Nov 2020 13:32:05 -0800 Subject: [PATCH 8/9] fix: mqtt as broker --- src/transports/mqtt.ts | 95 +++++++++++++++++++++++++++++++++++------- 1 file changed, 80 insertions(+), 15 deletions(-) diff --git a/src/transports/mqtt.ts b/src/transports/mqtt.ts index c6d1712a..8577eea3 100644 --- a/src/transports/mqtt.ts +++ b/src/transports/mqtt.ts @@ -1,42 +1,107 @@ -import AsyncMQTT, { AsyncClient } from "async-mqtt"; import ServerTransport, { JSONRPCRequest } from "./server-transport"; +import Aedes from "aedes"; +import tls from "tls"; +import net from "net"; export interface MQTTServerTransportOptions { - broker: string; inTopic: string; outTopic: string; + host: string; + protocol: "tcp"; + port: number | string; + /* + * Use filename of cert / key file. + */ + tls?: { + key: string; + cert: string; + }; } - export default class MQTTServerTransport extends ServerTransport { private options: MQTTServerTransportOptions; - public client: AsyncMQTT.AsyncClient | null; + private aedes: any; + public server: any; constructor(options: MQTTServerTransportOptions) { super(); this.options = { ...options }; - this.client = null; + + this.aedes = Aedes(); + + switch (this.options.protocol) { + case "tcp": + this.server = net.createServer(this.aedes.handle); + break; + } + + this.aedes.on("publish", (packet: any, client: any) => { + if (packet.topic !== "inTopic") { return; } + + const { payload } = packet; + const parsed = payload.toString(); + let jsonrpcRequest; + + try { + jsonrpcRequest = JSON.parse(parsed); + } catch (e) { + throw e; + } + + this.mqttRouterHandler(jsonrpcRequest, (v: string) => { + client.publish({ + topic: "outTopic", + payload: Buffer.from(v), + }, (e: Error) => { + if (e) { throw e; } + }); + }); + }); + } + + public async start(): Promise { + this.server.listen(this.options.port); } - public async connect(): Promise { - this.client = await AsyncMQTT.connectAsync(this.options.broker); - this.client.subscribe(this.options.inTopic); - this.client.on('message', (topic: string, payload: Buffer) => { - this.mqttRouterHandler(JSON.parse(payload.toString())); - }) + public stop(): Promise { + return new Promise((resolve) => { + this.aedes.close(() => { + this.server.close(); + resolve(); + }); + }); } - public end(): void { - this.client?.end(); + private publishMessageHandler(packet: any, client: any) { + if (packet.topic !== "inTopic") { return; } + + const { payload } = packet; + const parsed = payload.toString(); + let jsonrpcRequest; + + try { + jsonrpcRequest = JSON.parse(parsed); + } catch (e) { + throw e; + } + + this.mqttRouterHandler(jsonrpcRequest, (v: string) => { + client.publish({ + topic: "outTopic", + payload: Buffer.from(v), + }, (e: Error) => { + if (e) { throw e; } + }); + }); } - private async mqttRouterHandler(payload: any): Promise { + private async mqttRouterHandler(payload: any, respondWith: any): Promise { let result = null; if (payload instanceof Array) { result = await Promise.all(payload.map((r: JSONRPCRequest) => super.routerHandler(r))); } else { result = await super.routerHandler(payload); } - this.client?.publish(this.options.outTopic, JSON.stringify(result)); + return respondWith(JSON.stringify(result)); } } From 3b4d0b1f2318da8e2d015160760e0a37aaa63172 Mon Sep 17 00:00:00 2001 From: Zachary Belford Date: Tue, 3 Nov 2020 13:32:42 -0800 Subject: [PATCH 9/9] fix: update tests for broker --- src/transports/mqtt.test.ts | 44 +++++++++++++++---------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/transports/mqtt.test.ts b/src/transports/mqtt.test.ts index 9fc06590..1d7e96a0 100644 --- a/src/transports/mqtt.test.ts +++ b/src/transports/mqtt.test.ts @@ -1,7 +1,7 @@ import examples from "@open-rpc/examples"; import { parseOpenRPCDocument } from "@open-rpc/schema-utils-js"; import { Router } from "../router"; -import MQTTTransport from "./mqtt"; +import MQTTTransport, { MQTTServerTransportOptions } from "./mqtt"; import AsyncMQTT from "async-mqtt"; import Aedes from "aedes"; import Net from "net"; @@ -9,50 +9,42 @@ import Net from "net"; describe('mqtt transport', () => { const mqttBroker = Net.createServer(Aedes().handle); const mqttOptions = { - broker: "tcp://localhost:1883", + protocol: "tcp", + host: "localhost", + port: 1883, inTopic: "inTopic", outTopic: "outTopic" - } - let transport: MQTTTransport; - let mqttClient: AsyncMQTT.AsyncClient; - beforeAll(async () => { + } as MQTTServerTransportOptions + it("can answer to simple JSON-RPC", async (done) => { const simpleMathExample = await parseOpenRPCDocument(examples.simpleMath); - transport = new MQTTTransport(mqttOptions); + const transport = new MQTTTransport(mqttOptions); const router = new Router(simpleMathExample, { mockMode: true }); transport.addRouter(router); + transport.start(); + const uri = `${mqttOptions.protocol}://${mqttOptions.host}:${mqttOptions.port}`; + const mqttClient = await AsyncMQTT.connectAsync(uri) - mqttBroker.listen(1883); - await transport.connect(); - mqttClient = await AsyncMQTT.connectAsync(mqttOptions.broker) - mqttClient.subscribe(mqttOptions.outTopic) - }); + mqttClient.subscribe(mqttOptions.outTopic); - afterAll(() => { - transport.end(); - mqttBroker.close(); - }) - - it("can connect to the broker", () => { - expect(transport.client?.connected).toBeTruthy(); - }) - - it("can answer to simple JSON-RPC", (done) => { - const messageHandler = (topic: string, payload: Buffer) => { + const messageHandler = async (topic: string, payload: Buffer) => { const response = JSON.parse(payload.toString()); - expect(response.result).toBe(4); mqttClient.off('message', messageHandler); + await transport.stop(); + await mqttClient.end(); + expect(response.result).toBe(4); done(); } + mqttClient.on('message', messageHandler); - mqttClient.publish(mqttOptions.inTopic, JSON.stringify({ + await mqttClient.publish(mqttOptions.inTopic, JSON.stringify({ id: "0", jsonrpc: "2.0", method: "addition", params: [2, 2], - })) + })); }) });