From 528ee6be668dc5b953864b66f22a6c777a9f609e Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Mon, 16 Jan 2023 16:40:58 +0100 Subject: [PATCH 1/8] fix(mqtt): fixed how mqtt library is imported Because of some issues with some bundlers (namely, Parcel 2) we have updated the way mqtt.connect is imported in Connection.ts Minor updates to index.ts (eslint) Added a changelog section in readme file --- README.md | 28 +++++++++++++++ package-lock.json | 5 +-- package.json | 5 +-- rollup.config.js | 2 +- rollup.config.lib.js | 2 +- src/builder/APIConnectionBuilder.ts | 15 ++++---- src/connection/Connection.ts | 14 +++++--- src/index.lib.ts | 53 ++++++++++++++++------------- src/index.ts | 52 +++++++++++++++------------- 9 files changed, 111 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index f482606..9ee0cc9 100644 --- a/README.md +++ b/README.md @@ -162,3 +162,31 @@ ArduinoIoTCloud.connect(options) }) .catch(error => console.error(error)); ``` + +## Development + +### Testing +In order to test the library you have to export a couple of environment variables and then +launch a specific `npm` script as follows: + +```sh +$ export CLIENT_ID= +$ export CLIENT_SECRET= +$ npm run test +``` + +## Changelog +### [0.9.0] - 2023-01-16 + +#### Changed +A few development settings have been updated, this should not affect how the library works. +- 'mqtt' is imported differently if the library is used in the browser or in node. + In browser we're using 'mqtt/dist/mqtt' because of some issues with React with some bundlers (namely, Parcel 2) + + See: + + [https://github.com/mqttjs/MQTT.js/issues/1412#issuecomment-1193363330](https://github.com/mqttjs/MQTT.js/issues/1412#issuecomment-1193363330) + + [https://github.com/mqttjs/MQTT.js/issues/1233](https://github.com/mqttjs/MQTT.js/issues/1233) + +- updated README file with this changelog and some instructions about testing diff --git a/package-lock.json b/package-lock.json index e5f0b71..ddc4778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.7.1", + "version": "0.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -5988,7 +5988,8 @@ "dependencies": { "ansi-regex": { "version": "4.1.0", - "resolved": "", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "emoji-regex": { diff --git a/package.json b/package.json index c110521..15ea6b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.7.1", + "version": "0.9.0-alpha.1", "license": "GPLv3", "description": "JS module providing Arduino Create IoT Cloud Connection", "main": "./lib/index.js", @@ -58,7 +58,8 @@ "clean": "rimraf lib es", "build:es": "rollup -c", "build:lib": "rollup -c ./rollup.config.lib.js", - "build": "npm run clean && npm run build:es && npm run build:lib" + "build": "npm run clean && npm run build:es && npm run build:lib", + "dev": "rollup -c -w" }, "repository": { "type": "git", diff --git a/rollup.config.js b/rollup.config.js index 01d38d2..bc44a89 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,7 +20,7 @@ export default { resolve(), typescript(), commonjs(), - terser(), + // terser(), sizes() ] }; diff --git a/rollup.config.lib.js b/rollup.config.lib.js index 5588709..d0e3945 100644 --- a/rollup.config.lib.js +++ b/rollup.config.lib.js @@ -20,7 +20,7 @@ export default { resolve(), typescript(), commonjs(), - terser(), + // terser(), sizes() ] }; diff --git a/src/builder/APIConnectionBuilder.ts b/src/builder/APIConnectionBuilder.ts index 86ef5ea..15f7da7 100644 --- a/src/builder/APIConnectionBuilder.ts +++ b/src/builder/APIConnectionBuilder.ts @@ -1,3 +1,4 @@ +import { MqttClient } from 'mqtt'; import { IHttpClient } from '../http/IHttpClient'; import { Connection } from '../connection/Connection'; import { IConnection } from '../connection/IConnection'; @@ -10,8 +11,12 @@ type AccessResponse = { token_type: string; }; +function isApiOptions(options: CloudOptions): options is APIOptions { + return !!(options as APIOptions).clientId; +} + export class APIConnectionBuilder implements IConnectionBuilder { - constructor(private client: IHttpClient) {} + constructor(private client: IHttpClient, private mqttConnect: (string, IClientOptions) => MqttClient) {} public canBuild(options: CloudOptions): boolean { return isApiOptions(options); @@ -27,11 +32,7 @@ export class APIConnectionBuilder implements IConnectionBuilder { body.append('client_secret', options.clientSecret); body.append('audience', options.audience || 'https://api2.arduino.cc/iot'); - const { access_token } = await this.client.post(apiUrl, body, headers); - return Connection.From(options.host, options.port, access_token); + const { access_token: accessToken } = await this.client.post(apiUrl, body, headers); + return Connection.From(options.host, options.port, accessToken, this.mqttConnect); } } - -function isApiOptions(options: CloudOptions): options is APIOptions { - return !!(options as APIOptions).clientId; -} diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index 8a00540..891c306 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -1,5 +1,5 @@ import jws from 'jws'; -import mqtt from 'mqtt'; +import mqtt, { MqttClient } from 'mqtt'; import { Observable, Subject } from 'rxjs'; import SenML from '../senML'; @@ -34,7 +34,12 @@ export class Connection implements IConnection { }); } - public static async From(host: string, port: string | number, token: string): Promise { + public static async From( + host: string, + port: string | number, + token: string, + mqttConnect: (string, IClientOptions) => MqttClient + ): Promise { if (!token) throw new Error('connection failed: you need to provide a valid token'); if (!host) throw new Error('connection failed: you need to provide a valid host (broker)'); @@ -46,7 +51,7 @@ export class Connection implements IConnection { }; const connection = new Connection(); - connection.client = mqtt.connect(`wss://${host}:${port}/mqtt`, { + connection.client = mqttConnect(`wss://${host}:${port}/mqtt`, { ...BaseConnectionOptions, ...options, }); @@ -106,7 +111,8 @@ export class Connection implements IConnection { else valueToSend = value; }); - if (valueToSend !== {}) messages.push({ topic, propertyName: current, value: valueToSend }); + // the condition `if (valueToSend !== {}) ` has been removed bc it always evaluates to true + messages.push({ topic, propertyName: current, value: valueToSend }); return messages; } diff --git a/src/index.lib.ts b/src/index.lib.ts index 6862230..741776e 100644 --- a/src/index.lib.ts +++ b/src/index.lib.ts @@ -1,33 +1,38 @@ /* -* Copyright 2020 ARDUINO SA (http://www.arduino.cc/) -* This file is part of arduino-iot-js. -* Copyright (c) 2020 -* Authors: Fabrizio Mirabito, Francesco Pirrotta -* -* This software is released under: -* The GNU General Public License, which covers the main part of -* arduino-iot-js -* The terms of this license can be found at: -* https://www.gnu.org/licenses/gpl-3.0.en.html -* -* You can be released from the requirements of the above licenses by purchasing -* a commercial license. Buying such a license is mandatory if you want to modify or -* otherwise use the software for commercial activities involving the Arduino -* software without disclosing the source code of your own applications. To purchase -* a commercial license, send an email to license@arduino.cc. -* -*/ + * Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + * This file is part of arduino-iot-js. + * Copyright (c) 2020 + * Authors: Fabrizio Mirabito, Francesco Pirrotta + * + * This software is released under: + * The GNU General Public License, which covers the main part of + * arduino-iot-js + * The terms of this license can be found at: + * https://www.gnu.org/licenses/gpl-3.0.en.html + * + * You can be released from the requirements of the above licenses by purchasing + * a commercial license. Buying such a license is mandatory if you want to modify or + * otherwise use the software for commercial activities involving the Arduino + * software without disclosing the source code of your own applications. To purchase + * a commercial license, send an email to license@arduino.cc. + * + */ import SenML from './senML'; -import fetch from "node-fetch"; +import fetch from 'node-fetch'; +import mqtt from 'mqtt'; + import { HttpClientFactory } from './http/HttpClientFactory'; -import { CloudClient } from "./client/CloudClient"; -import { APIConnectionBuilder } from "./builder/APIConnectionBuilder"; -import { TokenConnectionBuilder } from "./builder/TokenConnectionBuilder"; +import { CloudClient } from './client/CloudClient'; +import { APIConnectionBuilder } from './builder/APIConnectionBuilder'; +import { TokenConnectionBuilder } from './builder/TokenConnectionBuilder'; -const builders = [new TokenConnectionBuilder(), new APIConnectionBuilder(HttpClientFactory.Create(fetch))]; +const builders = [ + new TokenConnectionBuilder(), + new APIConnectionBuilder(HttpClientFactory.Create(fetch), mqtt.connect), +]; const ArduinoIoTCloud = new CloudClient(builders); export { SenML }; export { ArduinoIoTCloud }; -export { CloudOptions, CloudMessageValue } from "./client/ICloudClient"; +export { CloudOptions, CloudMessageValue } from './client/ICloudClient'; diff --git a/src/index.ts b/src/index.ts index 896f273..9aeb39e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,33 +1,37 @@ /* -* Copyright 2020 ARDUINO SA (http://www.arduino.cc/) -* This file is part of arduino-iot-js. -* Copyright (c) 2020 -* Authors: Fabrizio Mirabito, Francesco Pirrotta -* -* This software is released under: -* The GNU General Public License, which covers the main part of -* arduino-iot-js -* The terms of this license can be found at: -* https://www.gnu.org/licenses/gpl-3.0.en.html -* -* You can be released from the requirements of the above licenses by purchasing -* a commercial license. Buying such a license is mandatory if you want to modify or -* otherwise use the software for commercial activities involving the Arduino -* software without disclosing the source code of your own applications. To purchase -* a commercial license, send an email to license@arduino.cc. -* -*/ + * Copyright 2020 ARDUINO SA (http://www.arduino.cc/) + * This file is part of arduino-iot-js. + * Copyright (c) 2020 + * Authors: Fabrizio Mirabito, Francesco Pirrotta + * + * This software is released under: + * The GNU General Public License, which covers the main part of + * arduino-iot-js + * The terms of this license can be found at: + * https://www.gnu.org/licenses/gpl-3.0.en.html + * + * You can be released from the requirements of the above licenses by purchasing + * a commercial license. Buying such a license is mandatory if you want to modify or + * otherwise use the software for commercial activities involving the Arduino + * software without disclosing the source code of your own applications. To purchase + * a commercial license, send an email to license@arduino.cc. + * + */ -import "whatwg-fetch"; +import 'whatwg-fetch'; +import mqtt from 'mqtt/dist/mqtt'; import SenML from './senML'; import { HttpClientFactory } from './http/HttpClientFactory'; -import { CloudClient } from "./client/CloudClient"; -import { APIConnectionBuilder } from "./builder/APIConnectionBuilder"; -import { TokenConnectionBuilder } from "./builder/TokenConnectionBuilder"; +import { CloudClient } from './client/CloudClient'; +import { APIConnectionBuilder } from './builder/APIConnectionBuilder'; +import { TokenConnectionBuilder } from './builder/TokenConnectionBuilder'; -const builders = [new TokenConnectionBuilder(), new APIConnectionBuilder(HttpClientFactory.Create(fetch))]; +const builders = [ + new TokenConnectionBuilder(), + new APIConnectionBuilder(HttpClientFactory.Create(fetch), mqtt.connect), +]; const ArduinoIoTCloud = new CloudClient(builders); export { SenML }; export { ArduinoIoTCloud }; -export { CloudOptions, CloudMessageValue } from "./client/ICloudClient"; +export { CloudOptions, CloudMessageValue } from './client/ICloudClient'; From 579d4340f8270753820a655bd8bad23eedc6b68e Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Mon, 16 Jan 2023 16:46:20 +0100 Subject: [PATCH 2/8] fix(mqtt): fixed how mqtt library is imported Minor fixes --- rollup.config.js | 2 +- rollup.config.lib.js | 2 +- src/connection/Connection.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index bc44a89..01d38d2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -20,7 +20,7 @@ export default { resolve(), typescript(), commonjs(), - // terser(), + terser(), sizes() ] }; diff --git a/rollup.config.lib.js b/rollup.config.lib.js index d0e3945..5588709 100644 --- a/rollup.config.lib.js +++ b/rollup.config.lib.js @@ -20,7 +20,7 @@ export default { resolve(), typescript(), commonjs(), - // terser(), + terser(), sizes() ] }; diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index 891c306..4428b25 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -1,5 +1,5 @@ import jws from 'jws'; -import mqtt, { MqttClient } from 'mqtt'; +import mqtt from 'mqtt'; import { Observable, Subject } from 'rxjs'; import SenML from '../senML'; @@ -38,7 +38,7 @@ export class Connection implements IConnection { host: string, port: string | number, token: string, - mqttConnect: (string, IClientOptions) => MqttClient + mqttConnect: (string, IClientOptions) => mqtt.MqttClient ): Promise { if (!token) throw new Error('connection failed: you need to provide a valid token'); if (!host) throw new Error('connection failed: you need to provide a valid host (broker)'); From 9d604886bbea5aeb0ca1e4186c7239c1ddd6ff66 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Mon, 16 Jan 2023 17:58:07 +0100 Subject: [PATCH 3/8] fix(mqtt): fixed how mqtt library is imported Regenerated package-lock.json --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index ddc4778..3cdc0c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0", + "version": "0.9.0-alpha.1", "lockfileVersion": 1, "requires": true, "dependencies": { From abed98c274998ef36d91ad4a5f1ef10cdd92abd7 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Mon, 16 Jan 2023 18:15:36 +0100 Subject: [PATCH 4/8] fix(mqtt): fixed how mqtt library is imported Updated TokenConnectionBuilder constructor to use the right mqtt.connect function --- package-lock.json | 2 +- package.json | 2 +- src/builder/TokenConnectionBuilder.ts | 5 ++++- src/index.lib.ts | 2 +- src/index.ts | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3cdc0c3..09450bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0-alpha.1", + "version": "0.9.0-alpha.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 15ea6b4..d98edcc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0-alpha.1", + "version": "0.9.0-alpha.2", "license": "GPLv3", "description": "JS module providing Arduino Create IoT Cloud Connection", "main": "./lib/index.js", diff --git a/src/builder/TokenConnectionBuilder.ts b/src/builder/TokenConnectionBuilder.ts index d563a07..7f99aea 100644 --- a/src/builder/TokenConnectionBuilder.ts +++ b/src/builder/TokenConnectionBuilder.ts @@ -1,14 +1,17 @@ +import { MqttClient } from 'mqtt'; import { Connection } from '../connection/Connection'; import { IConnection } from '../connection/IConnection'; import { IConnectionBuilder } from './IConnectionBuilder'; import { BrowserOptions, CloudOptions, BaseCloudOptions } from '../client/ICloudClient'; export class TokenConnectionBuilder implements IConnectionBuilder { + constructor(private mqttConnect: (string, IClientOptions) => MqttClient) {} + canBuild(options: CloudOptions): boolean { return !!(options as BrowserOptions).token; } build({ host, port, token }: BrowserOptions & BaseCloudOptions): Promise { - return Connection.From(host, port, token); + return Connection.From(host, port, token, this.mqttConnect); } } diff --git a/src/index.lib.ts b/src/index.lib.ts index 741776e..fa6f153 100644 --- a/src/index.lib.ts +++ b/src/index.lib.ts @@ -28,7 +28,7 @@ import { APIConnectionBuilder } from './builder/APIConnectionBuilder'; import { TokenConnectionBuilder } from './builder/TokenConnectionBuilder'; const builders = [ - new TokenConnectionBuilder(), + new TokenConnectionBuilder(mqtt.connect), new APIConnectionBuilder(HttpClientFactory.Create(fetch), mqtt.connect), ]; const ArduinoIoTCloud = new CloudClient(builders); diff --git a/src/index.ts b/src/index.ts index 9aeb39e..49b9f9c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,7 +27,7 @@ import { APIConnectionBuilder } from './builder/APIConnectionBuilder'; import { TokenConnectionBuilder } from './builder/TokenConnectionBuilder'; const builders = [ - new TokenConnectionBuilder(), + new TokenConnectionBuilder(mqtt.connect), new APIConnectionBuilder(HttpClientFactory.Create(fetch), mqtt.connect), ]; const ArduinoIoTCloud = new CloudClient(builders); From 0b2abb0eb8cd0ef0579e930e746b254da1690b8e Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Fri, 27 Jan 2023 13:16:42 +0100 Subject: [PATCH 5/8] feat: added check on empy object Added a check before sending MQTT empty objects. --- .gitignore | 3 ++- src/connection/Connection.ts | 7 +++++-- test/arduino-cloud.test.js | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 71731a0..f19f484 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules lib dist es -.tmp \ No newline at end of file +.tmp +misc \ No newline at end of file diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index 4428b25..869e9e4 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -111,8 +111,11 @@ export class Connection implements IConnection { else valueToSend = value; }); - // the condition `if (valueToSend !== {}) ` has been removed bc it always evaluates to true - messages.push({ topic, propertyName: current, value: valueToSend }); + // If the message is an object, and it's empty, it makes no sense to send it + // All other messages (e.g. non-empty objects or primitives) must be sent + if (!(typeof valueToSend === 'object' && Object.keys(valueToSend).length == 0)) { + messages.push({ topic, propertyName: current, value: valueToSend }); + } return messages; } diff --git a/test/arduino-cloud.test.js b/test/arduino-cloud.test.js index 291aaed..43c30bb 100644 --- a/test/arduino-cloud.test.js +++ b/test/arduino-cloud.test.js @@ -92,6 +92,12 @@ describe('Test the library basic functionalities', () => { await ArduinoIoTCloud.onPropertyValue(thingId, propertyBoolName, (value) => value === propertyBoolVal ? done() : null); sendPropertyAsDevice(deviceId, thingId, propertyBoolName, propertyBoolVal); }); + + it('Simulate client read boolean as FALSE property sent by device', async (done) => { + await ArduinoIoTCloud.onPropertyValue(thingId, propertyBoolName, (value) => !value ? done() : null); + sendPropertyAsDevice(deviceId, thingId, propertyBoolName, false); + }); + }) }); From 61dff681c9ac672186bb97e5d2388dc51b8193b4 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Fri, 27 Jan 2023 15:04:42 +0100 Subject: [PATCH 6/8] Bumped version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09450bb..d0283bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0-alpha.2", + "version": "0.9.0-alpha.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d98edcc..af756de 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0-alpha.2", + "version": "0.9.0-alpha.3", "license": "GPLv3", "description": "JS module providing Arduino Create IoT Cloud Connection", "main": "./lib/index.js", From ad11302e3a2c7f594bd1a1fced18279f2ae87e32 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Fri, 27 Jan 2023 17:01:08 +0100 Subject: [PATCH 7/8] Minor refactoring, created a 'isNotAnEmptyObject' function --- src/connection/Connection.ts | 5 ++--- src/utils/index.ts | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/connection/Connection.ts b/src/connection/Connection.ts index 869e9e4..65bc3b7 100644 --- a/src/connection/Connection.ts +++ b/src/connection/Connection.ts @@ -111,9 +111,8 @@ export class Connection implements IConnection { else valueToSend = value; }); - // If the message is an object, and it's empty, it makes no sense to send it - // All other messages (e.g. non-empty objects or primitives) must be sent - if (!(typeof valueToSend === 'object' && Object.keys(valueToSend).length == 0)) { + // Checking if valueToSend is NOT {} + if (Utils.isNotAnEmptyObject(valueToSend)) { messages.push({ topic, propertyName: current, value: valueToSend }); } diff --git a/src/utils/index.ts b/src/utils/index.ts index 810e0ba..c5c918a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -31,6 +31,10 @@ function isArray(value: CloudMessageValue): value is T[] { return Array.isArray(value); } +function isNotAnEmptyObject(value): boolean { + return !(typeof value === 'object' && Object.keys(value).length == 0); +} + function toArrayBuffer(buf: { length: number }): ArrayBuffer { const ab = new ArrayBuffer(buf.length); const view = new Uint8Array(ab); @@ -69,4 +73,5 @@ export default { toArrayBuffer, toBuffer, arrayBufferToBase64, + isNotAnEmptyObject, }; From ff2488924b6c38ae7a25b713615f35727af851f8 Mon Sep 17 00:00:00 2001 From: Christian Sarnataro Date: Fri, 27 Jan 2023 17:11:58 +0100 Subject: [PATCH 8/8] Bumped version; added nvmrc file --- .nvmrc | 1 + package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 .nvmrc diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..cab13a7 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v14.17.0 diff --git a/package-lock.json b/package-lock.json index d0283bd..ddc4778 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0-alpha.3", + "version": "0.9.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index af756de..7070478 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-iot-js", - "version": "0.9.0-alpha.3", + "version": "0.9.0", "license": "GPLv3", "description": "JS module providing Arduino Create IoT Cloud Connection", "main": "./lib/index.js",