Browse Source

Create a working development environment, update README.md and .gitignore

Miroslav Abrahám 5 tháng trước cách đây
mục cha
commit
58cd390e21

+ 1 - 0
.gitignore

@@ -1,6 +1,7 @@
 # dirs
 .DS_Store
 logs
+node_modules
 distro
 
 # files

+ 25 - 0
README.md

@@ -125,8 +125,33 @@ Here as well, you are able to provide a custom duration: `runAllZones(600)` (for
 
 ------
 
+## Development
+
+In order to install the development environment, please run the following code:
+
+```bash
+python -m venv distro/python-linux
+source distro/python-linux/bin/activate
+pip install nodeenv
+nodeenv --node=16.0.0 --npm=8.1.0 --with-npm distro/nodejs-linux
+deactivate
+
+source distro/nodejs-linux/bin/activate
+npm install axios@1.4.0
+npm install -D @types/node@18.16.8 rimraf@5.0.0 typescript@5.0.4
+deactivate_node
+```
+
+Then to build run
+```
+npm run build
+```
+
+------
+
 ## Contributors
 
+* Miroslav Abrahám (kunago) - Further modifications and fixes of the code
 * Martijn Dierckx - Complete rewrite to service both the cloud & local API binding in TypeScript
 * [Paul Molluzzo](https://paul.molluzzo.com) - Initial 0.1.0 version containing the cloud binding
 

+ 1 - 0
dist/Hydrawise.d.ts

@@ -1,4 +1,5 @@
 /**
+ * @author Miroslav Abrahám - Further modifications and fixes
  * @author Martijn Dierckx - Complete rewrite to service both the cloud & local API binding
  * @author Paul Molluzzo (https://paulmolluzzo.com) - Initial 0.1.0 version containing the cloud binding
  */

+ 1 - 1
dist/Hydrawise.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"Hydrawise.d.ts","sourceRoot":"","sources":["../src/Hydrawise.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAK5D,UAAU,sBAAsB;IAC/B,IAAI,EAAG,uBAAuB,CAAC;IAC/B,IAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,sEAAsE;AACtE,qBAAa,SAAS;IAErB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+C;IACjE,IAAI,EAAE,uBAAuB,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IAE/B;;;;;;;;OAQG;gBACS,OAAO,EAAE,sBAAsB;IAY3C;;;;;OAKG;IACH,OAAO,CAAC,OAAO;IA0Cf;;;;;;;OAOG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAwCxG;;;;;;OAMG;IACI,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,mBAAmB,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAmClH;;;;;OAKG;IACI,OAAO,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIpF;;;;OAIG;IACI,WAAW,CAAC,UAAU,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIrF;;;;;OAKG;IACI,WAAW,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIxF;;;;;OAKG;IACI,eAAe,CAAC,UAAU,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIzF;;;;OAIG;IACI,QAAQ,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIlE;;;OAGG;IACI,YAAY,CAAC,UAAU,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC;IAInE;;;;OAIG;IACI,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAgFpF;;;OAGG;IACI,cAAc,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAsDvD;;;;OAIG;IACI,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAWrD;;;;OAIG;IACI,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAa9D;;;;;;;;;OASG;IACI,OAAO,CAAC,MAAM,GAAE,GAAQ,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAUnE"}
+{"version":3,"file":"Hydrawise.d.ts","sourceRoot":"","sources":["../src/Hydrawise.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAM5D,UAAU,sBAAsB;IAC/B,IAAI,EAAG,uBAAuB,CAAC;IAC/B,IAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAI,CAAC,EAAE,MAAM,CAAA;CACb;AAED,sEAAsE;AACtE,qBAAa,SAAS;IAErB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+C;IACjE,IAAI,EAAE,uBAAuB,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IAE/B;;;;;;;;OAQG;gBACS,OAAO,EAAE,sBAAsB;IAY3C;;;;;OAKG;IACH,OAAO,CAAC,OAAO;IA0Cf;;;;;;;OAOG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAwCxG;;;;;;OAMG;IACI,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,mBAAmB,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAmClH;;;;;OAKG;IACI,OAAO,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIpF;;;;OAIG;IACI,WAAW,CAAC,UAAU,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIrF;;;;;OAKG;IACI,WAAW,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIxF;;;;;OAKG;IACI,eAAe,CAAC,UAAU,CAAC,EAAE,mBAAmB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIzF;;;;OAIG;IACI,QAAQ,CAAC,WAAW,EAAE,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAIlE;;;OAGG;IACI,YAAY,CAAC,UAAU,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,GAAG,CAAC;IAInE;;;;OAIG;IACI,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,GAAG,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAiFpF;;;OAGG;IACI,cAAc,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAsDvD;;;;OAIG;IACI,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAWrD;;;;OAIG;IACI,oBAAoB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAa9D;;;;;;;;;OASG;IACI,OAAO,CAAC,MAAM,GAAE,GAAQ,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;CAUnE"}

+ 37 - 35
dist/Hydrawise.js

@@ -1,5 +1,6 @@
 "use strict";
 /**
+ * @author Miroslav Abrahám - Further modifications and fixes
  * @author Martijn Dierckx - Complete rewrite to service both the cloud & local API binding
  * @author Paul Molluzzo (https://paulmolluzzo.com) - Initial 0.1.0 version containing the cloud binding
  */
@@ -226,44 +227,45 @@ class Hydrawise {
                 // Check every returned relay
                 data.relays.map((z) => {
                     // Only configured zones
-                    if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.CLOUD || z.lastwaterepoch != 0) {
-                        // Zone
-                        let zone = {
-                            apiBinding: that,
-                            relayID: z.relay_id,
-                            zone: z.relay,
-                            name: z.name,
-                            nextRunAt: new Date((data.time + z.time) * 1000),
-                            nextRunDuration: z.run || z.run_seconds,
-                            isSuspended: z.suspended !== undefined && z.suspended == 1,
-                            isRunning: false,
-                            remainingRunningTime: 0
-                        };
-                        // Link controller to the zones if it was provided when calling the method
-                        if (controller !== undefined && controller !== null && controller instanceof HydrawiseController_1.HydrawiseController) {
-                            zone.controller = controller;
-                        }
-                        // Only available data for local connections
-                        if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL) {
-                            zone.defaultRunDuration = z.normalRuntime * 60;
-                        }
-                        // Running? (local connection)
-                        if (data.running !== undefined) {
-                            let runningZone = data.running.find((x) => {
-                                return x.relay_id == z.relay_id;
-                            });
-                            if (runningZone != undefined && runningZone != null) {
-                                zone.isRunning = true;
-                                zone.remainingRunningTime = runningZone.time_left;
-                            }
-                        }
-                        // Running? (cloud connection)
-                        if (z.time == 1) {
+                    // Commented out because it may drive some zones unusable from time to time by filtering them out
+                    // if(that.type == HydrawiseConnectionType.CLOUD || z.lastwaterepoch != 0){
+                    // Zone
+                    let zone = {
+                        apiBinding: that,
+                        relayID: z.relay_id,
+                        zone: z.relay,
+                        name: z.name,
+                        nextRunAt: new Date((data.time + z.time) * 1000),
+                        nextRunDuration: z.run || z.run_seconds,
+                        isSuspended: z.suspended !== undefined && z.suspended == 1,
+                        isRunning: false,
+                        remainingRunningTime: 0
+                    };
+                    // Link controller to the zones if it was provided when calling the method
+                    if (controller !== undefined && controller !== null && controller instanceof HydrawiseController_1.HydrawiseController) {
+                        zone.controller = controller;
+                    }
+                    // Only available data for local connections
+                    if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL) {
+                        zone.defaultRunDuration = z.normalRuntime * 60;
+                    }
+                    // Running? (local connection)
+                    if (data.running !== undefined) {
+                        let runningZone = data.running.find((x) => {
+                            return x.relay_id == z.relay_id;
+                        });
+                        if (runningZone != undefined && runningZone != null) {
                             zone.isRunning = true;
-                            zone.remainingRunningTime = z.run;
+                            zone.remainingRunningTime = runningZone.time_left;
                         }
-                        zones.push(new HydrawiseZone_1.HydrawiseZone(zone));
                     }
+                    // Running? (cloud connection)
+                    if (z.time == 1) {
+                        zone.isRunning = true;
+                        zone.remainingRunningTime = z.run;
+                    }
+                    zones.push(new HydrawiseZone_1.HydrawiseZone(zone));
+                    // }
                 });
                 resolve(zones);
             }).catch((err) => {

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
dist/Hydrawise.js.map


+ 8 - 0
hydrawise-api.code-workspace

@@ -0,0 +1,8 @@
+{
+	"folders": [
+		{
+			"path": "."
+		}
+	],
+	"settings": {}
+}

+ 393 - 110
package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "hydrawise-api",
-  "version": "1.2.1",
+  "version": "1.2.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "hydrawise-api",
-      "version": "1.2.1",
+      "version": "1.2.2",
       "license": "MIT",
       "dependencies": {
         "axios": "^1.4.0"
@@ -55,9 +55,9 @@
       "dev": true
     },
     "node_modules/ansi-regex": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
-      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
       "dev": true,
       "engines": {
         "node": ">=12"
@@ -100,14 +100,26 @@
       "dev": true
     },
     "node_modules/brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
       "dev": true,
       "dependencies": {
         "balanced-match": "^1.0.0"
       }
     },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/color-convert": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -138,9 +150,9 @@
       }
     },
     "node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
       "dev": true,
       "dependencies": {
         "path-key": "^3.1.0",
@@ -159,6 +171,19 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/eastasianwidth": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -171,10 +196,51 @@
       "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
       "dev": true
     },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/follow-redirects": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
-      "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
+      "version": "1.15.9",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
       "funding": [
         {
           "type": "individual",
@@ -191,12 +257,12 @@
       }
     },
     "node_modules/foreground-child": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
-      "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+      "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
       "dev": true,
       "dependencies": {
-        "cross-spawn": "^7.0.0",
+        "cross-spawn": "^7.0.6",
         "signal-exit": "^4.0.1"
       },
       "engines": {
@@ -207,38 +273,128 @@
       }
     },
     "node_modules/form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
+      "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
       "dependencies": {
         "asynckit": "^0.4.0",
         "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
         "mime-types": "^2.1.12"
       },
       "engines": {
         "node": ">= 6"
       }
     },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/glob": {
-      "version": "10.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.3.tgz",
-      "integrity": "sha512-Kb4rfmBVE3eQTAimgmeqc2LwSnN0wIOkkUL6HmxEFxNJ4fHghYHVbFba/HcGcRjE6s9KoMNK3rSOwkL4PioZjg==",
+      "version": "10.4.5",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+      "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
       "dev": true,
       "dependencies": {
         "foreground-child": "^3.1.0",
-        "jackspeak": "^2.0.3",
-        "minimatch": "^9.0.0",
-        "minipass": "^5.0.0",
-        "path-scurry": "^1.7.0"
+        "jackspeak": "^3.1.2",
+        "minimatch": "^9.0.4",
+        "minipass": "^7.1.2",
+        "package-json-from-dist": "^1.0.0",
+        "path-scurry": "^1.11.1"
       },
       "bin": {
-        "glob": "dist/cjs/src/bin.js"
+        "glob": "dist/esm/bin.mjs"
       },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
       "engines": {
-        "node": ">=16 || 14 >=14.17"
+        "node": ">= 0.4"
       },
       "funding": {
-        "url": "https://github.com/sponsors/isaacs"
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
       }
     },
     "node_modules/is-fullwidth-code-point": {
@@ -257,16 +413,13 @@
       "dev": true
     },
     "node_modules/jackspeak": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz",
-      "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==",
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+      "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
       "dev": true,
       "dependencies": {
         "@isaacs/cliui": "^8.0.2"
       },
-      "engines": {
-        "node": ">=14"
-      },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
       },
@@ -275,12 +428,17 @@
       }
     },
     "node_modules/lru-cache": {
-      "version": "9.1.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz",
-      "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==",
-      "dev": true,
+      "version": "10.4.3",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+      "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+      "dev": true
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
       "engines": {
-        "node": "14 || >=16.14"
+        "node": ">= 0.4"
       }
     },
     "node_modules/mime-db": {
@@ -303,9 +461,9 @@
       }
     },
     "node_modules/minimatch": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz",
-      "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==",
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
       "dev": true,
       "dependencies": {
         "brace-expansion": "^2.0.1"
@@ -318,14 +476,20 @@
       }
     },
     "node_modules/minipass": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
-      "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
       "dev": true,
       "engines": {
-        "node": ">=8"
+        "node": ">=16 || 14 >=14.17"
       }
     },
+    "node_modules/package-json-from-dist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+      "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+      "dev": true
+    },
     "node_modules/path-key": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -336,16 +500,16 @@
       }
     },
     "node_modules/path-scurry": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.8.0.tgz",
-      "integrity": "sha512-IjTrKseM404/UAWA8bBbL3Qp6O2wXkanuIE3seCxBH7ctRuvH1QRawy1N3nVDHGkdeZsjOsSe/8AQBL/VQCy2g==",
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+      "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
       "dev": true,
       "dependencies": {
-        "lru-cache": "^9.1.1",
-        "minipass": "^5.0.0"
+        "lru-cache": "^10.2.0",
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
       },
       "engines": {
-        "node": ">=16 || 14 >=14.17"
+        "node": ">=16 || 14 >=14.18"
       },
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
@@ -396,9 +560,9 @@
       }
     },
     "node_modules/signal-exit": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz",
-      "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
       "dev": true,
       "engines": {
         "node": ">=14"
@@ -467,9 +631,9 @@
       }
     },
     "node_modules/strip-ansi": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
-      "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
       "dev": true,
       "dependencies": {
         "ansi-regex": "^6.0.1"
@@ -652,9 +816,9 @@
       "dev": true
     },
     "ansi-regex": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
-      "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
       "dev": true
     },
     "ansi-styles": {
@@ -685,14 +849,23 @@
       "dev": true
     },
     "brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
       "dev": true,
       "requires": {
         "balanced-match": "^1.0.0"
       }
     },
+    "call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "requires": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      }
+    },
     "color-convert": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -717,9 +890,9 @@
       }
     },
     "cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
       "dev": true,
       "requires": {
         "path-key": "^3.1.0",
@@ -732,6 +905,16 @@
       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
       "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
     },
+    "dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "requires": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      }
+    },
     "eastasianwidth": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -744,42 +927,131 @@
       "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
       "dev": true
     },
+    "es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
+    },
+    "es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
+    },
+    "es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "requires": {
+        "es-errors": "^1.3.0"
+      }
+    },
+    "es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "requires": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      }
+    },
     "follow-redirects": {
-      "version": "1.15.1",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
-      "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
+      "version": "1.15.9",
+      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="
     },
     "foreground-child": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
-      "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+      "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
       "dev": true,
       "requires": {
-        "cross-spawn": "^7.0.0",
+        "cross-spawn": "^7.0.6",
         "signal-exit": "^4.0.1"
       }
     },
     "form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz",
+      "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==",
       "requires": {
         "asynckit": "^0.4.0",
         "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
         "mime-types": "^2.1.12"
       }
     },
+    "function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+    },
+    "get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "requires": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      }
+    },
+    "get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "requires": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      }
+    },
     "glob": {
-      "version": "10.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.3.tgz",
-      "integrity": "sha512-Kb4rfmBVE3eQTAimgmeqc2LwSnN0wIOkkUL6HmxEFxNJ4fHghYHVbFba/HcGcRjE6s9KoMNK3rSOwkL4PioZjg==",
+      "version": "10.4.5",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+      "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
       "dev": true,
       "requires": {
         "foreground-child": "^3.1.0",
-        "jackspeak": "^2.0.3",
-        "minimatch": "^9.0.0",
-        "minipass": "^5.0.0",
-        "path-scurry": "^1.7.0"
+        "jackspeak": "^3.1.2",
+        "minimatch": "^9.0.4",
+        "minipass": "^7.1.2",
+        "package-json-from-dist": "^1.0.0",
+        "path-scurry": "^1.11.1"
+      }
+    },
+    "gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
+    },
+    "has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
+    },
+    "has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "requires": {
+        "has-symbols": "^1.0.3"
+      }
+    },
+    "hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "requires": {
+        "function-bind": "^1.1.2"
       }
     },
     "is-fullwidth-code-point": {
@@ -795,9 +1067,9 @@
       "dev": true
     },
     "jackspeak": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz",
-      "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==",
+      "version": "3.4.3",
+      "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+      "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
       "dev": true,
       "requires": {
         "@isaacs/cliui": "^8.0.2",
@@ -805,11 +1077,16 @@
       }
     },
     "lru-cache": {
-      "version": "9.1.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz",
-      "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==",
+      "version": "10.4.3",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+      "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
       "dev": true
     },
+    "math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
+    },
     "mime-db": {
       "version": "1.52.0",
       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -824,18 +1101,24 @@
       }
     },
     "minimatch": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz",
-      "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==",
+      "version": "9.0.5",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
       "dev": true,
       "requires": {
         "brace-expansion": "^2.0.1"
       }
     },
     "minipass": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
-      "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+      "version": "7.1.2",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+      "dev": true
+    },
+    "package-json-from-dist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+      "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
       "dev": true
     },
     "path-key": {
@@ -845,13 +1128,13 @@
       "dev": true
     },
     "path-scurry": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.8.0.tgz",
-      "integrity": "sha512-IjTrKseM404/UAWA8bBbL3Qp6O2wXkanuIE3seCxBH7ctRuvH1QRawy1N3nVDHGkdeZsjOsSe/8AQBL/VQCy2g==",
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+      "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
       "dev": true,
       "requires": {
-        "lru-cache": "^9.1.1",
-        "minipass": "^5.0.0"
+        "lru-cache": "^10.2.0",
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
       }
     },
     "proxy-from-env": {
@@ -884,9 +1167,9 @@
       "dev": true
     },
     "signal-exit": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz",
-      "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==",
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
       "dev": true
     },
     "string-width": {
@@ -935,9 +1218,9 @@
       }
     },
     "strip-ansi": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
-      "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
       "dev": true,
       "requires": {
         "ansi-regex": "^6.0.1"

+ 3 - 2
package.json

@@ -1,10 +1,10 @@
 {
   "name": "hydrawise-api",
-  "version": "1.2.1",
+  "version": "1.2.2",
   "description": "Library for accessing the Hydrawise API via the cloud or directly on the local network",
   "repository": {
     "type": "git",
-    "url": "https://github.com/paulmolluzzo/hydrawise-api.git"
+    "url": "https://git.kunago.com/kunago/node-hydrawise-api.git"
   },
   "main": "dist/index.js",
   "type": "commonjs",
@@ -25,6 +25,7 @@
     "test": "echo \"Error: no test specified\" && exit 1"
   },
   "contributors": [
+    "Miroslav Abrahám",
     "Martijn Dierckx",
     "Paul Molluzzo (https://paul.molluzzo.com)"
   ],

+ 372 - 0
src/Hydrawise.js

@@ -0,0 +1,372 @@
+"use strict";
+/**
+ * @author Miroslav Abrahám - Further modifications and fixes
+ * @author Martijn Dierckx - Complete rewrite to service both the cloud & local API binding
+ * @author Paul Molluzzo (https://paulmolluzzo.com) - Initial 0.1.0 version containing the cloud binding
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Hydrawise = void 0;
+var HydrawiseConnectionType_1 = require("./HydrawiseConnectionType");
+var HydrawiseZone_1 = require("./HydrawiseZone");
+var HydrawiseController_1 = require("./HydrawiseController");
+var HydrawiseCommandException_1 = require("./HydrawiseCommandException");
+var axios_1 = require("axios");
+/** Class representing a Hydrawise local or cloud based API binding */
+var Hydrawise = /** @class */ (function () {
+    /**
+     * Create a new instance of the Hydrawise API binding
+     * @param {object} options - Options object containing all parameters
+     * @param {string} options.type - The type of binding you wish to make: 'CLOUD' or 'LOCAL'
+     * @param {string} [options.host] - The hostname or ip address of the local host you wish to connect to. Only needed for local bindings.
+     * @param {string} [options.user = admin] - The username of the local Hydrawise controller. Only needed for local bindings (falls back to the default 'admin' user).
+     * @param {string} [options.password] - The password of the local Hydrawise controller. Only needed for local bindings.
+     * @param {string} [options.key] - The API key of your Hydrawise cloud account. Only needed for cloud bindings.
+     */
+    function Hydrawise(options) {
+        this.cloudUrl = 'https://app.hydrawise.com/api/v1/';
+        this.type = options.type || HydrawiseConnectionType_1.HydrawiseConnectionType.CLOUD; // CLOUD or LOCAL 
+        this.url = (this.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL ? 'http://' + options.host + '/' : this.cloudUrl);
+        // Local Auth
+        this.localAuthUsername = options.user || 'admin';
+        this.localAuthPassword = options.password || '';
+        // Cloud Auth
+        this.cloudAuthAPIkey = options.key || '';
+    }
+    /**
+     * Private function that makes a GET request to the local or cloud Hydrawise server
+     * @param {string} path - The path of the API endpoint
+     * @param {object} [params] - Parameters to be added to the URL path
+     * @return {Promise} A Promise which will be resolved when the request has returned from the local or cloud server.
+     */
+    Hydrawise.prototype.request = function (path, params) {
+        var _this = this;
+        if (path === void 0) { path = ''; }
+        if (params === void 0) { params = {}; }
+        var promise = new Promise(function (resolve, reject) {
+            // setup basic request
+            var options = {
+                method: 'get',
+                url: _this.url + path,
+                params: params,
+                json: true
+            };
+            // Basic auth for local binding
+            if (_this.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL) {
+                var authBuffer = Buffer.from(_this.localAuthUsername + ':' + _this.localAuthPassword);
+                options.headers = {
+                    'Authorization': 'Basic ' + authBuffer.toString('base64')
+                };
+            }
+            // API key auth for cloud binding
+            else {
+                options.params.api_key = _this.cloudAuthAPIkey;
+            }
+            // Send request
+            (0, axios_1.default)(options).then(function (response) {
+                //Check for errors
+                if (response.data.messageType == 'error') {
+                    reject(new HydrawiseCommandException_1.HydrawiseCommandException(response.data.message));
+                }
+                resolve(response.data);
+            }).catch(function (err) {
+                reject(err);
+            });
+        });
+        // return request
+        return promise;
+    };
+    /**
+     * Sends a command to a single zone/relay
+     * @param {string} action - The required command to be executed for the given zone/relay: run, suspend, stop
+     * @param {(HydrawiseZone|number|number)} zoneOrRelay - The zone/relay you are targetting. Can be a zone object returned by getZones, a relay number (zone.zone) for local bindings or a relayID (zone.relayID) for cloud bindings
+     * @param {number} [duration] - How long should the command be executed (only applicable for run & suspend)
+     * @todo Allow using a controller id instead of HydrawiseController object.
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.commandZone = function (action, zoneOrRelay, duration) {
+        var that = this;
+        // Get started
+        var promise = new Promise(function (resolve, reject) {
+            var opts = {
+                period_id: 998,
+                action: action,
+            };
+            // Set Relay number for local binding
+            if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL) {
+                opts.relay = zoneOrRelay instanceof HydrawiseZone_1.HydrawiseZone ? zoneOrRelay.zone : zoneOrRelay; // A zone object, as returned by getZones, or just the relayID can be sent
+            }
+            // Set Relay ID for cloud binding
+            else {
+                opts.relay_id = zoneOrRelay instanceof HydrawiseZone_1.HydrawiseZone ? zoneOrRelay.relayID : zoneOrRelay; // A zone object, as returned by getZones, or just the relayID can be sent
+            }
+            // Custom duration?
+            if (duration !== undefined) {
+                opts.custom = duration;
+            }
+            // Set controller if one was provided (only for cloud)
+            if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.CLOUD && zoneOrRelay instanceof HydrawiseZone_1.HydrawiseZone && zoneOrRelay.controller !== undefined && zoneOrRelay.controller instanceof HydrawiseController_1.HydrawiseController) {
+                opts.controller_id = zoneOrRelay.controller.id;
+            }
+            // Execute command
+            that.setZone(opts).then(function (data) {
+                resolve(data);
+            }).catch(function (err) {
+                reject(err);
+            });
+        });
+        return promise;
+    };
+    /**
+     * Sends a command to all zones/relays
+     * @param {string} action - The required command to be executed: runall, suspendall, stopall
+     * @param {number} [duration] - How long should the given command be executed (only applicable for runall & suspendall)
+     * @todo Check whether controller_id needs to sent when the account contains multiple zones
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.commandAllZones = function (action, controller, duration) {
+        var that = this;
+        // Get started
+        var promise = new Promise(function (resolve, reject) {
+            var opts = {
+                period_id: 998,
+                action: action
+            };
+            // Custom duration?
+            if (duration !== undefined) {
+                opts.custom = duration;
+            }
+            // Specific controller? (only cloud)
+            if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.CLOUD && controller !== undefined && controller !== null) {
+                if (controller instanceof HydrawiseController_1.HydrawiseController) {
+                    opts.controller_id = controller.id;
+                }
+                else {
+                    opts.controller_id = controller;
+                }
+            }
+            that.setZone(opts).then(function (data) {
+                resolve(data);
+            }).catch(function (err) {
+                reject(err);
+            });
+        });
+        return promise;
+    };
+    /**
+     * Sends the run command to a single zone/relay
+     * @param {(HydrawiseZone|number)} zoneOrRelay - The zone/relay you are targetting. Can be a zone object returned by getZones, a relay number (zone.zone) for local bindings or a relayID (zone.relayID) for cloud bindings
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.runZone = function (zoneOrRelay, duration) {
+        return this.commandZone('run', zoneOrRelay, duration);
+    };
+    /**
+     * Sends the run command to all zones/relays
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.runAllZones = function (controller, duration) {
+        return this.commandAllZones('runall', controller, duration);
+    };
+    /**
+     * Sends the suspend command to a single zone/relay
+     * @param {(HydrawiseZone|number)} zoneOrRelay - The zone/relay you are targetting. Can be a zone object returned by getZones, a relay number (zone.zone) for local bindings or a relayID (zone.relayID) for cloud bindings
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.suspendZone = function (zoneOrRelay, duration) {
+        return this.commandZone('suspend', zoneOrRelay, duration);
+    };
+    /**
+     * Sends the suspend command to all zones/relays for a specific controller
+     * @param {number} [duration] - How long should the command be executed
+     * @param {HydrawiseController|number} [controller] - Return zones for a specific controller. If not specified, the zones of the deault controller are returned.
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.suspendAllZones = function (controller, duration) {
+        return this.commandAllZones('suspendall', controller, duration);
+    };
+    /**
+     * Sends the stop command to a single zone/relay
+     * @param {(HydrawiseZone|number)} zoneOrRelay - The zone/relay you are targetting. Can be a zone object returned by getZones, a relay number (zone.zone) for local bindings or a relayID (zone.relayID) for cloud bindings
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.stopZone = function (zoneOrRelay) {
+        return this.commandZone('stop', zoneOrRelay);
+    };
+    /**
+     * Sends the stop command to all zones/relays
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    Hydrawise.prototype.stopAllZones = function (controller) {
+        return this.commandAllZones('stopall', controller);
+    };
+    /**
+     * Retrieves all zones/relays known to the server
+     * @param {HydrawiseController|number} [controller] - Return zones for a specific controller. If not specified, the zones of the deault controller are returned.
+     * @return {Promise} A Promise which will be resolved when all zones have been retrieved
+     */
+    Hydrawise.prototype.getZones = function (controller) {
+        var that = this;
+        // Get started
+        var promise = new Promise(function (resolve, reject) {
+            // Controller set?
+            var controllerID;
+            if (controller !== undefined && controller !== null) {
+                if (controller instanceof HydrawiseController_1.HydrawiseController) {
+                    controllerID = controller.id;
+                }
+                else {
+                    controllerID = controller;
+                }
+            }
+            // Get relays
+            that.getStatusAndSchedule(controllerID).then(function (data) {
+                var zones = [];
+                // Check every returned relay
+                data.relays.map(function (z) {
+                    // Only configured zones
+                    // Commented out because it drive the zones unusable from time to time by filtering them out
+                    // if(that.type == HydrawiseConnectionType.CLOUD || z.lastwaterepoch != 0){
+                    // Zone
+                    var zone = {
+                        apiBinding: that,
+                        relayID: z.relay_id,
+                        zone: z.relay,
+                        name: z.name,
+                        nextRunAt: new Date((data.time + z.time) * 1000),
+                        nextRunDuration: z.run || z.run_seconds,
+                        isSuspended: z.suspended !== undefined && z.suspended == 1,
+                        isRunning: false,
+                        remainingRunningTime: 0
+                    };
+                    // Link controller to the zones if it was provided when calling the method
+                    if (controller !== undefined && controller !== null && controller instanceof HydrawiseController_1.HydrawiseController) {
+                        zone.controller = controller;
+                    }
+                    // Only available data for local connections
+                    if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL) {
+                        zone.defaultRunDuration = z.normalRuntime * 60;
+                    }
+                    // Running? (local connection)
+                    if (data.running !== undefined) {
+                        var runningZone = data.running.find(function (x) {
+                            return x.relay_id == z.relay_id;
+                        });
+                        if (runningZone != undefined && runningZone != null) {
+                            zone.isRunning = true;
+                            zone.remainingRunningTime = runningZone.time_left;
+                        }
+                    }
+                    // Running? (cloud connection)
+                    if (z.time == 1) {
+                        zone.isRunning = true;
+                        zone.remainingRunningTime = z.run;
+                    }
+                    zones.push(new HydrawiseZone_1.HydrawiseZone(zone));
+                    // }
+                });
+                resolve(zones);
+            }).catch(function (err) {
+                reject(err);
+            });
+        });
+        return promise;
+    };
+    /**
+     * Retrieves all controllers known to the Hydrawise cloud or returns a single dummy one for a local connection
+     * @return {Promise} A Promise which will be resolved when all controllers have been retrieved
+     */
+    Hydrawise.prototype.getControllers = function () {
+        var _this = this;
+        var that = this;
+        // Get started
+        var promise = new Promise(function (resolve, reject) {
+            // Cloud
+            if (that.type == HydrawiseConnectionType_1.HydrawiseConnectionType.CLOUD) {
+                // Get Controllers
+                _this.getCustomerDetails('controllers').then(function (data) {
+                    var controllers = [];
+                    // Check every returned relay
+                    data.controllers.map(function (c) {
+                        // Controller
+                        var controller = {
+                            apiBinding: that,
+                            id: c.controller_id,
+                            name: c.name,
+                            serialNumber: c.serial_number,
+                            lastContactWithCloud: new Date(c.last_contact * 1000),
+                            status: c.status
+                        };
+                        controllers.push(new HydrawiseController_1.HydrawiseController(controller));
+                    });
+                    resolve(controllers);
+                }).catch(function (err) {
+                    reject(err);
+                });
+            }
+            // Local
+            else {
+                // Controller
+                var controller = {
+                    apiBinding: that,
+                    name: that.url
+                };
+                resolve([new HydrawiseController_1.HydrawiseController(controller)]);
+            }
+        });
+        return promise;
+    };
+    /* -------- Raw API calls -------- */
+    /**
+     * Gets the customer ID & list of available controllers configured in the Hydrawise cloud. Only available in cloud binding.
+     * @param {string} type - Defines the type of customer details to be retrieved alongside the customer ID
+     * @return {Promise} A Promise which will be resolved when the request has returned from the cloud server.
+     */
+    Hydrawise.prototype.getCustomerDetails = function (type) {
+        // Cloud only API
+        if (this.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL) {
+            return new Promise(function (resolve, reject) {
+                reject(new HydrawiseCommandException_1.HydrawiseCommandException('Calling Cloud API function on a Local Binding'));
+            });
+        }
+        return this.request('customerdetails.php', { type: type });
+    };
+    /**
+     * Gets the status and schedule of the locally connected controller or all controllers in the cloud
+     * @param {number} [controller] - Return the status and schedule for a specific controller. If not specified, the zones of the deault controller are returned.
+     * @return {Promise} A Promise which will be resolved when the request has returned from the local or cloud server.
+     */
+    Hydrawise.prototype.getStatusAndSchedule = function (controller) {
+        var uri = (this.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL ? 'get_sched_json.php' : 'statusschedule.php');
+        var params = {};
+        // Was a controller set?
+        if (controller !== undefined && controller !== null) {
+            params.controller_id = controller;
+        }
+        // If no controller was set
+        return this.request(uri, params);
+    };
+    /**
+     * Sends an action request to a specific or all zones
+     * @param {object} params - Parameters object containing all parameters to be sent along with the request
+     * @param {string} [params.relay_id] - The id of the relay which needs to be targetted. Not needed for runall, suspendall, stopall
+     * @param {string} params.action - The action to be executed: run, stop, suspend, runall, suspendall, stopall
+     * @param {number} [params.custom] - The amount of seconds the action needs to be run. Only for run, suspend, runall, suspendall
+     * @param {number} [controller] - Needs to be specified if you have multiple controllers (cloud only)
+     * @todo Complete params documentation
+     * @return {Promise} A Promise which will be resolved when the request has returned from the local or cloud server.
+     */
+    Hydrawise.prototype.setZone = function (params, controller) {
+        if (params === void 0) { params = {}; }
+        var uri = (this.type == HydrawiseConnectionType_1.HydrawiseConnectionType.LOCAL ? 'set_manual_data.php' : 'setzone.php');
+        // Was a controller set?
+        if (controller !== undefined && controller !== null) {
+            params.controller_id = controller;
+        }
+        return this.request(uri, params);
+    };
+    return Hydrawise;
+}());
+exports.Hydrawise = Hydrawise;

+ 6 - 3
src/Hydrawise.ts

@@ -1,4 +1,5 @@
 /**
+ * @author Miroslav Abrahám - Further modifications and fixes
  * @author Martijn Dierckx - Complete rewrite to service both the cloud & local API binding
  * @author Paul Molluzzo (https://paulmolluzzo.com) - Initial 0.1.0 version containing the cloud binding
  */
@@ -8,7 +9,8 @@ import { HydrawiseZone } from './HydrawiseZone';
 import { HydrawiseController } from './HydrawiseController';
 import { HydrawiseCommandException } from './HydrawiseCommandException';
 import Axios from 'axios';
-import { ifError } from 'assert';
+
+declare const Buffer: { from: (arg0: string) => any; }
 
 interface HydrawiseConfiguration {
 	type : HydrawiseConnectionType,
@@ -273,7 +275,8 @@ export class Hydrawise {
 				data.relays.map((z: any) => {
 					
 					// Only configured zones
-					if(that.type == HydrawiseConnectionType.CLOUD || z.lastwaterepoch != 0){
+					// Commented out because it may drive some zones unusable from time to time by filtering them out
+					// if(that.type == HydrawiseConnectionType.CLOUD || z.lastwaterepoch != 0){
 					
 						// Zone
 						let zone: any = {
@@ -316,7 +319,7 @@ export class Hydrawise {
 						}
 						
 						zones.push(new HydrawiseZone(zone));
-					}
+					// }
 				});
 
 				resolve(zones);

+ 39 - 0
src/HydrawiseCommandException.js

@@ -0,0 +1,39 @@
+"use strict";
+/**
+ * @author Martijn Dierckx
+ */
+var __extends = (this && this.__extends) || (function () {
+    var extendStatics = function (d, b) {
+        extendStatics = Object.setPrototypeOf ||
+            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
+            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
+        return extendStatics(d, b);
+    };
+    return function (d, b) {
+        if (typeof b !== "function" && b !== null)
+            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
+        extendStatics(d, b);
+        function __() { this.constructor = d; }
+        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+    };
+})();
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.HydrawiseCommandException = void 0;
+/** Class representing a specifc error triggered by the Hydrawise API binding */
+var HydrawiseCommandException = /** @class */ (function (_super) {
+    __extends(HydrawiseCommandException, _super);
+    function HydrawiseCommandException(message) {
+        var params = [];
+        for (var _i = 1; _i < arguments.length; _i++) {
+            params[_i - 1] = arguments[_i];
+        }
+        var _this = _super.apply(this, params) || this;
+        Error.captureStackTrace(_this, HydrawiseCommandException);
+        _this.name = 'HydrawiseCommandException';
+        _this.message = message;
+        _this.date = new Date();
+        return _this;
+    }
+    return HydrawiseCommandException;
+}(Error));
+exports.HydrawiseCommandException = HydrawiseCommandException;

+ 13 - 0
src/HydrawiseConnectionType.js

@@ -0,0 +1,13 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.HydrawiseConnectionType = void 0;
+/**
+ * Enumeration for the different types of Hydrawise API bindings: Cloud or Local
+ * @readonly
+ * @enum {string}
+ */
+var HydrawiseConnectionType;
+(function (HydrawiseConnectionType) {
+    HydrawiseConnectionType["LOCAL"] = "LOCAL";
+    HydrawiseConnectionType["CLOUD"] = "CLOUD";
+})(HydrawiseConnectionType || (exports.HydrawiseConnectionType = HydrawiseConnectionType = {}));

+ 59 - 0
src/HydrawiseController.js

@@ -0,0 +1,59 @@
+"use strict";
+/**
+ * @author Martijn Dierckx
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.HydrawiseController = void 0;
+/** Class representing a Hydrawise controller */
+var HydrawiseController = /** @class */ (function () {
+    /**
+     * Create a new instance of a HydrawiseController
+     * @param {object} options - Options object containing all parameters
+     * @param {Hydrawise} options.apiBinding - The API binding which can be used to execute commands on the zone
+     * @param {number} options.id - The unique identifier of the controller
+     * @param {string} options.name - The name of the controller
+     * @param {string} options.serialNumber - The serial number of the controller
+     * @param {Date} options.lastContactWithCloud - The last date time the controller was able to contact/sync with the cloud
+     * @param {string} options.status - The status as returned by the Hydrawise cloud
+     */
+    function HydrawiseController(options) {
+        this.apiBinding = options.apiBinding;
+        this.id = options.id;
+        this.name = options.name;
+        this.serialNumber = options.serialNumber;
+        this.lastContactWithCloud = options.lastContactWithCloud;
+        this.status = options.status;
+    }
+    /**
+     * Retrieves all zones/relays known to the server for this controller
+     * @return {Promise} A Promise which will be resolved when all zones have been retrieved
+     */
+    HydrawiseController.prototype.getZones = function () {
+        return this.apiBinding.getZones(this);
+    };
+    /**
+     * Sends the run command to all the zones/relays of the controller
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    HydrawiseController.prototype.runAllZones = function (duration) {
+        return this.apiBinding.commandAllZones('runall', this, duration);
+    };
+    /**
+     * Sends the stop command to all the zones/relays of the controller
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    HydrawiseController.prototype.stopAllZones = function () {
+        return this.apiBinding.commandAllZones('stopall', this);
+    };
+    /**
+     * Sends the suspend command to all the zones/relays of the controller
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    HydrawiseController.prototype.suspendAllZones = function (duration) {
+        return this.apiBinding.commandAllZones('suspendall', this, duration);
+    };
+    return HydrawiseController;
+}());
+exports.HydrawiseController = HydrawiseController;

+ 60 - 0
src/HydrawiseZone.js

@@ -0,0 +1,60 @@
+"use strict";
+/**
+ * @author Martijn Dierckx
+ */
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.HydrawiseZone = void 0;
+/** Class representing a Hydrawise zone */
+var HydrawiseZone = /** @class */ (function () {
+    /**
+     * Create a new instance of a HydrawiseZone
+     * @param {object} options - Options object containing all parameters
+     * @param {Hydrawise} options.apiBinding - The API binding which can be used to execute commands on the zone
+     * @param {number} options.relayID - The unique relay number known to the Hydrawise cloud
+     * @param {number} options.zone - The local zone/relay number
+     * @param {string} options.name - The name of the zone
+     * @param {Date} options.nextRunAt - The date & time of the next scheduled run
+     * @param {number} options.nextRunDuration - Run time in seconds of the next run defined by nextRunAt
+     * @param {boolean} options.isSuspended - Returns true when the zoneis currently suspended
+     * @param {boolean} options.isRunning - Returns true when the zone is actively running
+     * @param {number} options.remainingRunningTime - Remaining run time in seconds when isRunning = true
+     * @param {HydrawiseController} [options.controller] - The controller linked to the zone
+     */
+    function HydrawiseZone(options) {
+        this.apiBinding = options.apiBinding;
+        this.relayID = options.relayID;
+        this.zone = options.zone;
+        this.name = options.name;
+        this.nextRunAt = options.nextRunAt;
+        this.nextRunDuration = options.nextRunDuration;
+        this.isSuspended = options.isSuspended;
+        this.isRunning = options.isRunning;
+        this.remainingRunningTime = options.remainingRunningTime;
+        this.controller = options.controller;
+    }
+    /**
+     * Sends the run command to the zone/relay
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    HydrawiseZone.prototype.run = function (duration) {
+        return this.apiBinding.commandZone('run', this, duration);
+    };
+    /**
+     * Sends the stop command to the zone/relay
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    HydrawiseZone.prototype.stop = function () {
+        return this.apiBinding.commandZone('stop', this);
+    };
+    /**
+     * Sends the suspend command to the zone/relay
+     * @param {number} [duration] - How long should the command be executed
+     * @return {Promise} A Promise which will be resolved when the command has been executed.
+     */
+    HydrawiseZone.prototype.suspend = function (duration) {
+        return this.apiBinding.commandZone('suspend', this, duration);
+    };
+    return HydrawiseZone;
+}());
+exports.HydrawiseZone = HydrawiseZone;

+ 21 - 0
src/index.js

@@ -0,0 +1,21 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    var desc = Object.getOwnPropertyDescriptor(m, k);
+    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+      desc = { enumerable: true, get: function() { return m[k]; } };
+    }
+    Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+    if (k2 === undefined) k2 = k;
+    o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./Hydrawise"), exports);
+__exportStar(require("./HydrawiseZone"), exports);
+__exportStar(require("./HydrawiseController"), exports);
+__exportStar(require("./HydrawiseConnectionType"), exports);
+__exportStar(require("./HydrawiseCommandException"), exports);

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác